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

推荐阅读
  • 本文详细介绍了Oracle 11g中的创建表空间的方法,以及如何设置客户端和服务端的基本配置,包括用户管理、环境变量配置等。 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • Redis:缓存与内存数据库详解
    本文介绍了数据库的基本分类,重点探讨了关系型与非关系型数据库的区别,并详细解析了Redis作为非关系型数据库的特点、工作模式、优点及持久化机制。 ... [详细]
  • 本文介绍了 Oracle SQL 中的集合运算、子查询、数据处理、表的创建与管理等内容。包括查询部门号为10和20的员工信息、使用集合运算、子查询的注意事项、数据插入与删除、表的创建与修改等。 ... [详细]
  • 如何在Django框架中实现对象关系映射(ORM)
    本文介绍了Django框架中对象关系映射(ORM)的实现方式,通过ORM,开发者可以通过定义模型类来间接操作数据库表,从而简化数据库操作流程,提高开发效率。 ... [详细]
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • 本文介绍了如何在两个Oracle数据库(假设为数据库A和数据库B)之间设置DBLink,以便能够从数据库A中直接访问和操作数据库B中的数据。文章详细描述了创建DBLink前的必要准备步骤以及具体的创建方法。 ... [详细]
  • 本文详细探讨了BCTF竞赛中窃密木马题目的解题策略,重点分析了该题目在漏洞挖掘与利用方面的技巧。 ... [详细]
  • 题目编号:2049 [SDOI2008]Cave Exploration。题目描述了一种动态图操作场景,涉及三种基本操作:断开两个节点间的连接(destroy(a,b))、建立两个节点间的连接(connect(a,b))以及查询两节点是否连通(query(a,b))。所有操作均确保图中无环存在。 ... [详细]
  • oracle 对硬件环境要求,Oracle 10G数据库软硬件环境的要求 ... [详细]
  • Vulnhub DC3 实战记录与分析
    本文记录了在 Vulnhub DC3 靶机上的渗透测试过程,包括漏洞利用、内核提权等关键步骤,并总结了实战经验和教训。 ... [详细]
  • Oracle 10g 和 11g 32位 OCI.DLL 文件下载
    32位 PL/SQL Developer 访问 64位 Oracle 11g 数据库时,需要使用 32位的 OCI.DLL 文件以确保正常连接和数据访问。本文将详细介绍如何获取并配置此文件。 ... [详细]
  • 本文介绍了 PHP 的基本概念、服务器与客户端的工作原理,以及 PHP 如何与数据库交互。同时,还涵盖了常见的数据库操作和安全性问题。 ... [详细]
  • GreenPlum采纳ShareNothing的架构,良好的施展了便宜PC的作用。自此IO不在是DW(datawarehouse)的瓶颈,相同网络的压力会大很多。然而GreenPlum的查问优化策略可能防止尽量少的网络替换。对于首次接触GreenPlum的人来说,必定耳目一新。 ... [详细]
  • 在运行于MS SQL Server 2005的.NET 2.0 Web应用中,我偶尔会遇到令人头疼的SQL死锁问题。过去,我们主要通过调整查询来解决这些问题,但这既耗时又不可靠。我希望能找到一种确定性的查询模式,确保从设计上彻底避免SQL死锁。 ... [详细]
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社区 版权所有