热门标签 | 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;不走索引在这里插入图片描述

推荐阅读
  • 本文深入探讨了MySQL中常见的面试问题,包括事务隔离级别、存储引擎选择、索引结构及优化等关键知识点。通过详细解析,帮助读者在面对BAT等大厂面试时更加从容。 ... [详细]
  • 本文详细介绍了C++中map容器的多种删除和交换操作,包括clear、erase、swap、extract和merge方法,并提供了完整的代码示例。 ... [详细]
  • 目录一、salt-job管理#job存放数据目录#缓存时间设置#Others二、returns模块配置job数据入库#配置returns返回值信息#mysql安全设置#创建模块相关 ... [详细]
  • 社交网络中的级联行为 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 全面解析运维监控:白盒与黑盒监控及四大黄金指标
    本文深入探讨了白盒和黑盒监控的概念,以及它们在系统监控中的应用。通过详细分析基础监控和业务监控的不同采集方法,结合四个黄金指标的解读,帮助读者更好地理解和实施有效的监控策略。 ... [详细]
  • 1.介绍有时候我们需要一些模拟数据来进行测试,今天简单记录下如何用存储过程生成一些随机数据。2.建表我们新建一张学生表和教师表如下:CREATETABLEstudent(idINT ... [详细]
  • 本文详细介绍如何使用 Apache Spark 执行基本任务,包括启动 Spark Shell、运行示例程序以及编写简单的 WordCount 程序。同时提供了参数配置的注意事项和优化建议。 ... [详细]
  • 本文介绍如何从包含多个记录的会员表中,筛选出同时拥有BookID为10和14的会员。通过SQL查询语句,可以有效地获取符合条件的MemberID。 ... [详细]
  • PHP 实现多级树形结构:构建无限层级分类系统
    在众多管理系统中,如菜单、分类和部门等模块,通常需要处理层级结构。为了高效管理和展示这些层级数据,本文将介绍如何使用 PHP 实现多级树形结构,并提供代码示例以帮助开发者轻松实现无限分级。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • ElasticSearch 集群监控与优化
    本文详细介绍了如何有效地监控 ElasticSearch 集群,涵盖了关键性能指标、集群健康状况、统计信息以及内存和垃圾回收的监控方法。 ... [详细]
  • 由二叉树到贪心算法
    二叉树很重要树是数据结构中的重中之重,尤其以各类二叉树为学习的难点。单就面试而言,在 ... [详细]
  • 优化Flask应用的并发处理:解决Mysql连接过多问题
    本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
  • 访问一个网页的全过程
    准备:DHCPUDPIP和以太网启动主机,用一根以太网电缆连接到学校的以太网交换机,交换机又与学校的路由器相连.学校的这台路由器与一个ISP链接,此ISP(Intern ... [详细]
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社区 版权所有