热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Mysql】九、Mysql高级篇索引

MYSQL索引一、什么是索引?二、索引数据结构1、mysql数据库的四种索引2、BTREE结构三、索引分类、创建索引、查看索引1、单值索引2、复合索引3、函数索引4、

MYSQL索引

      • 一、什么是索引?
      • 二、索引数据结构
        • 1、mysql数据库的四种索引
        • 2、BTREE结构
      • 三、索引分类、创建索引、查看索引
        • 1、单值索引
        • 2、复合索引
        • 3、函数索引
        • 4、删除索引
        • 5、查看索引
      • 四、什么情况需要建立索引?
      • 五、EXPLAIN 字段属性
        • 1、EXPLAIN -- id(表的读取顺序):
        • 2、EXPLAIN -- select_type(数据读取操作):
        • 3、EXPLAIN -- type(如何读取数据):
        • 4、EXPLAIN -- possible_keys(显示可能用到的索引):
        • 5、EXPLAIN -- key(查询实际用到的索引):
        • 6、EXPLAIN -- key_len(索引显示的字节数):
        • 7、EXPLAIN -- ref(显示索引的使用列):
        • 8、EXPLAIN -- row(查询的行数):
        • 9、EXPLAIN -- filtered(读取行数占比):
        • 10、EXPLAIN -- extra(扩展):
      • 六、索引优化原则


查看本表的索引:
mysql:SHOW INDEX FROM 表名
oracle:SELECT * FROM USER_IND_COLUMNS WHERE TABLE_NAME = '表名'


一、什么是索引?

在这里插入图片描述
索引优势:

  1. 相当于书的目录,提高数据库查询效率,降低数据库io操作成本。
  2. 通过索引对数据库进行排序,降低排序成本,减轻cpu负荷
    索引劣势:
  3. 建立索引相当于存储了另一张表记录了索引的模型,该表保存主键与索引字段,所以索引列也需要占用内存空间。
  4. 索引虽然提高了查询效率,但是同时也降低了增删改的效率。因为每次新增修改删除,都需要更新索引列字段的B+树,降低增删改的时间。

二、索引数据结构


1、mysql数据库的四种索引


  • BTREE:最广泛的索引类型,大部分索引都是支持该类型
  • HASH:只有memory引擎支持,用途相对较少
  • R-tree(空间索引):MYISAM引擎,用途少,不介绍
  • Full-text(全文索引):MYISAM引擎,InnoDB丛mysql5.6版本之后支持该索引
    在这里插入图片描述
    创建索引没有特殊指定时,默认创建的都是BTREE索引

2、BTREE结构

btree叫做多路平衡搜索树,一颗m叉的btree树有如下特性:

  1. 树中每个节点最多包含m个孩子
  2. 除去根节点和叶子节点外,每个节点最多有m/2(向上取整 5/2=2.5 取 3)个孩子
  3. 如根节点不是叶子节点,则至少有两个孩子
  4. 所有叶子节点都在同一层
  5. 每个非叶子节点都有n个key和n+1个指针组成

三、索引分类、创建索引、查看索引

个人主推方式二进行所有创建修改等操作

1、单值索引

方式1: CREATE INDEX index_name ON table_name(column)
方式2: ALTER TABLE table_name ADD INDEX index_name(column)

2、复合索引

方式1: CREATE INDEX composite_index_name ON table_name(col1, col2)
方式2: ALTER TABLE table_name ADD INDEX composite_index_name(col1, col2)

3、函数索引

函数索引是MySql8.0支持的,之前版本不支持该函数索引

-- 创建函数索引
ALTER TABLE books ADD KEY idx_fun_data((DATE(created_time))) -- 注意函数需要用()包住,否则报错
ALTER TABLE books ADD KEY idx_fun_data((DATE(created_time)))-- 查看当前索引
mysql> SHOW INDEX FROM books;
+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------------------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------------------------+
| books | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | | YES | NULL |
| books | 1 | idx_fun_data | 1 | NULL | A | 1 | NULL | NULL | YES | BTREE | | | YES | cast(`created_time` as date) |
| books | 1 | idx_fun_contact | 1 | NULL | A | 3 | NULL | NULL | YES | BTREE | | | YES | concat(`name`,`writer`) |
+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------------------------+

explain查看是否使用索引

-- key = idx_fun_data 使用函数索引
mysql> EXPLAIN SELECT * FROM books WHERE DATE(created_time)='2000-1-1';
+----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | books | NULL | ref | idx_fun_data | idx_fun_data | 4 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+----------+-------+-- key = idx_fun_contact 使用函数索引
mysql> EXPLAIN SELECT CONCAT(name, writer) FROM books WHERE CONCAT(name, writer) = 'sssssss';
+----+-------------+-------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | books | NULL | ref | idx_fun_contact | idx_fun_contact | 123 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------+

4、删除索引

方式一DROP INDEX index_name ON table_name
方式二:ALTER TABLE table_name DROP INDEX index_name

5、查看索引


  • mysql:
    SHOW INDEX FROM '表名'
    在这里插入图片描述
  • oracle:
    SELECT * FROM USER_IND_COLUMNS WHERE TABLE_NAME = '表名'

四、什么情况需要建立索引?

适合创建索引

  1. 主键索引
  2. 频繁查询的字段需要创建索引(例如:微信号或者商品编号)
  3. 与其他表关联的外键需要
  4. 查询中分组的字段
  5. 查询中排序的字段 order by
  6. 字段列值重复度较底的情况下

不适合创建索引

  1. 频繁更新的字段不适合建立索引
  2. where语句用不到的需要建索引
  3. 表记录太少不要建立索引
  4. 某个字段包含许多重复的内容,不要建立索引(例如:性别字段只保存男/女)

五、EXPLAIN 字段属性


explain是模拟mysql查询优化器执行sql,可以看出mysql是如何优化执行你的sql语句。


explain有什么用?

  • 读取表的顺序
  • 数据读取操作的操作累心
  • 哪些索引可以使用
  • 哪些索引被实际使用
  • 表之间的引用
  • 每张表多少行被查询优化器查询


1、EXPLAIN – id(表的读取顺序):


  • id相同:执行顺序是由上而下
    在这里插入图片描述
  • id不同: ID值越大越先执行
    在这里插入图片描述
  • id相同和不同,同时存在: ID越大优先级越高,ID相同顺序执行
    在这里插入图片描述

2、EXPLAIN – select_type(数据读取操作):


select_type属性含义
SIMPLE简单的select查询,不包含子查询和UNION
PRIMARY查询中包含任何复杂的子查询部分,最外层标记为PRIMARY,最后执行
SUBQUERYselect或者where子句包含子查询
DERIVEDfrom列表中包含子查询(表连接)mysql会递归这些子查询,将子查询结果放在临时表中
UNION第二个select出现在union之后,标记为UNION(union包含在from子句中,外层select标记为DERIV-DR)
UNION RESULT连接两个select语句的UNION

图例为UNION RESULT
在这里插入图片描述

3、EXPLAIN – type(如何读取数据):

type字段属性
效率从好到差依次为:system > const > eq_ref > ref > range > index > ALL
查询中至少达到range,最好可以达到ref

type属性含义
ALL全表扫描
INDEX读取索引,与ALL都是全表扫描,ALL读硬盘,INDEX读索引,降低了IO操作
RANGE只检索指定的行&#xff0c;where语句中的IN、between、<、>等范围查询
REF非唯一扫描&#xff0c;主表的关联约束可以匹配子表多行&#xff0c;一对多的情况
EQ_REF读取主表中和关联表&#xff0c;表中的每行组合成的一行
CONST通过索引一次找到&#xff0c;常见与主键约束(PRIMARY KEY) / 唯一约束(UNIQUE)&#xff0c;很快的将主键置于where列表中&#xff0c;mysql可以将该查询转化成一个常量
SYSTEM表记录只有一行&#xff08;是const的特例&#xff09;

ALL:
在这里插入图片描述

INDEX:
在这里插入图片描述
RANGE:
在这里插入图片描述
REF&#xff1a;
在这里插入图片描述

EQ_REF:
在这里插入图片描述
CONST:
在这里插入图片描述
SYSTEM:
在这里插入图片描述
在这里插入图片描述

4、EXPLAIN – possible_keys&#xff08;显示可能用到的索引&#xff09;:

查询字段存在多个索引&#xff0c;将会被列出&#xff0c;但不一定会使用
在这里插入图片描述

5、EXPLAIN – key&#xff08;查询实际用到的索引&#xff09;:


  1. 实际使用到的索引&#xff0c;NULL表示没有用到索引&#xff0c;不为NULL则是实际使用到的索引
    在这里插入图片描述

  2. 查询中若使用了覆盖索引&#xff0c;则改索引仅出现在key列表中
    覆盖索引&#xff1a;SQL只需要通过索引就可以返回查询所需要的数据&#xff0c;而不必通过二级索引查到主键之后再去查询数据
    如下所示&#xff0c;user_idid建立了联合索引&#xff0c;所以查询结果会直接从索引中读取结果&#xff0c;而不需要全表扫描
    在这里插入图片描述


6、EXPLAIN – key_len&#xff08;索引显示的字节数&#xff09;:

显示的是最大可能长度&#xff0c;并非实际使用长度
不损失精度的情况下&#xff0c;越小越好&#xff0c;速度越快

7、EXPLAIN – ref&#xff08;显示索引的使用列&#xff09;:

如果索引固定查询一个值的话显示的是const&#xff0c;表示一个常量
在这里插入图片描述
如果使用了某个字段去匹配则显示&#xff0c;users.id表示被使用的字段&#xff0c;&#xff0c;null表示没有使用到索引去匹配行。
在这里插入图片描述

8、EXPLAIN – row&#xff08;查询的行数&#xff09;:


  1. 未建索引查询的行数&#xff1a;
    在这里插入图片描述
  2. 建索引查询的行数&#xff1a;
    在这里插入图片描述

9、EXPLAIN – filtered&#xff08;读取行数占比&#xff09;:

filtered表示的是&#xff1a;返回结果的行数占需读取行数的百分比

案例模拟隐试类型转化的索引搜索&#xff1a;

直接索引搜索

-- 走索引只查了一行&#xff0c;结果也是一行&#xff0c;所以filtered&#61;100%
mysql> explain select * from testt where name &#61; &#39;2000&#39;;
&#43;----&#43;-------------&#43;-------&#43;------------&#43;------&#43;---------------&#43;------------&#43;---------&#43;-------&#43;------&#43;----------&#43;-------------&#43;
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
&#43;----&#43;-------------&#43;-------&#43;------------&#43;------&#43;---------------&#43;------------&#43;---------&#43;-------&#43;------&#43;----------&#43;-------------&#43;
| 1 | SIMPLE | testt | NULL | ref | name_index | name_index | 33 | const | 1 | 100.00 | Using index |
&#43;----&#43;-------------&#43;-------&#43;------------&#43;------&#43;---------------&#43;------------&#43;---------&#43;-------&#43;------&#43;----------&#43;-------------&#43;

类型转化走where再走索引

-- 走索引查了两行&#xff0c;结果是一行&#xff0c;所以filtered&#61;50%
mysql> explain select * from testt where name &#61; 2000;
&#43;----&#43;-------------&#43;-------&#43;------------&#43;-------&#43;---------------&#43;------------&#43;---------&#43;------&#43;------&#43;----------&#43;--------------------------&#43;
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
&#43;----&#43;-------------&#43;-------&#43;------------&#43;-------&#43;---------------&#43;------------&#43;---------&#43;------&#43;------&#43;----------&#43;--------------------------&#43;
| 1 | SIMPLE | testt | NULL | index | name_index | name_index | 33 | NULL | 2 | 50.00 | Using where; Using index |
&#43;----&#43;-------------&#43;-------&#43;------------&#43;-------&#43;---------------&#43;------------&#43;---------&#43;------&#43;------&#43;----------&#43;--------------------------&#43;

10、EXPLAIN – extra&#xff08;扩展&#xff09;:


  1. Using filesort 文件排序
    使用外部的索引排序&#xff0c;而不是按照表内的索引顺序读取。无法利用索引直接排序操作叫做‘文件排序’
  2. Using temporary
    使用零时表保存中间结果&#xff0c;查询排序结果时使用临时表&#xff0c;常见order by 和 group by&#xff0c;效率低下
  3. Using index
    使用了索引&#xff0c;表示效率不错。
    如果同时出现Using where&#xff0c;表示索引被用来执行索引键值的查找。
    如果没有出现Using where&#xff0c;表示索引用来读取数据而非查找
  4. Using where
    使用了where过滤条件
  5. Using Join Buffer
    使用了连接缓存
  6. Impossible WHERE
    where的值得总是false&#xff0c;不可获取元素&#xff0c;例如 where 1 &#61; 2
  7. Using index condition
    会先条件过滤索引&#xff0c;过滤完索引后找到所有符合索引条件的数据行&#xff0c;随后用 WHERE 子句中的其他条件去过滤这些数据行
    在这里插入图片描述

六、索引优化原则

在这里插入图片描述

  1. 全值匹配
    如果是联合索引&#xff0c;按照最左匹配原则&#xff0c;查询要从最左列开始&#xff0c;并且不跳过索引中的列

-- 索引按照 user_id,project_name,id 顺序建立
ALTER TABLE projects ADD INDEX user_id_index_test(user_id,project_name,id) COMMENT &#39;测试索引&#39;-- 查询也按照 user_id,project_name,id 顺序查询
SELECT * FROM projects WHERE user_id &#61; 18 AND project_name &#61; &#39;zhangsan&#39; AND id &#61; 1-- 最左匹配原则&#xff0c;不用 user_id 开头&#xff0c;用不上索引
SELECT * FROM projects WHERE project_name &#61; &#39;zhangsan&#39; AND id &#61; 1

  1. 不要再索引列上做任何操作
    计算、函数、自动or手动类型转化&#xff0c;否则索引失效&#xff0c;全表扫描
    使用函数&#xff1a;
    在这里插入图片描述
    不使用函数&#xff1a;
    在这里插入图片描述
  2. 联合索引中&#xff0c;使用范围查询后右边的列索引失效

-- 使用范围后的列索引失效
SELECT * FROM projects WHERE user_id > 18 AND project_name &#61; &#39;zhangsan&#39; AND id &#61; 1
-- 如上 user_id 使用range查找后&#xff0c;project_name、id无法使用全职匹配查找&#xff0c;&#xff0c;&#xff0c;此时联合索引只用上了user_id的范围查找。

  1. 少用select *&#xff08;只访问索引列&#xff0c;索引列和查询列一致&#xff09;
    要什么取什么&#xff0c;不要使用*取出所有的值

  2. <>!&#61;无法使用索引

  3. is nullis not null无法使用索引

  4. like开头的 ‘%admin’ 索引失效
    解决办法&#xff1a;使用覆盖索引

-- select字段必须是索引字段
select name from projects where name like &#39;%hhhh%&#39;

  1. 隐试类型转换不走索引

-- project_name是字符串类型&#xff0c;使用20000会隐试转化类型为字符串
EXPLAIN SELECT * FROM projects WHERE project_name &#61; 20000

类型不一致&#xff0c;隐试转换的情况&#xff0c;不走索引
在这里插入图片描述
按照字段原类型查询&#xff0c;走索引
在这里插入图片描述

  1. 少用or&#xff0c;不走索引在这里插入图片描述

推荐阅读
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 解读MySQL查询执行计划的详细指南
    本文旨在帮助开发者和数据库管理员深入了解如何解读MySQL查询执行计划。通过详细的解析,您将掌握优化查询性能的关键技巧,了解各种访问类型和额外信息的含义。 ... [详细]
  • PHP 编程疑难解析与知识点汇总
    本文详细解答了 PHP 编程中的常见问题,并提供了丰富的代码示例和解决方案,帮助开发者更好地理解和应用 PHP 知识。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 解决PHP与MySQL连接时出现500错误的方法
    本文详细探讨了当使用PHP连接MySQL数据库时遇到500内部服务器错误的多种解决方案,提供了详尽的操作步骤和专业建议。无论是初学者还是有经验的开发者,都能从中受益。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • MySQL缓存机制深度解析
    本文详细探讨了MySQL的缓存机制,包括主从复制、读写分离以及缓存同步策略等内容。通过理解这些概念和技术,读者可以更好地优化数据库性能。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • 根据最新发布的《互联网人才趋势报告》,尽管大量IT从业者已转向Python开发,但随着人工智能和大数据领域的迅猛发展,仍存在巨大的人才缺口。本文将详细介绍如何使用Python编写一个简单的爬虫程序,并提供完整的代码示例。 ... [详细]
author-avatar
cometcui
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有