author:JevonWei

版权声明:原创作品


索引基础:

索引:提取索引的创建在的表上字段中的数据,构建出一个独特的数据结构;

索引的作用:加速查询操作;副作用:降低写操作性能;
表中数据子集:把表中某个或某些字段的数据提取出来另存为一个特定数据结构组织的数据;
某个字段或某些字段:WHERE子句中用到的字段; 索引类型:B+ TREE Index,HASH Index、Fulltext Index、Spacial Index
B+ TREE:顺序存储,每一个叶子结点到根结点的距离相同;左前缀索引,适合于范围类型的数据查询; 适用于B+ TREE索引的查询类型:全键值、键值范围或键前缀;
全值匹配:精确匹配某个值;
WHERE COLUMN = 'value';
匹配最左前缀:只精确匹配起头的部分;
WEHRE COLUMN LIKE 'PREFIX%';
匹配范围值:
精确匹配某一列,范围匹配另一列;
只用访问索引的查询:覆盖索引;
index(Name)
SELECT Name FROM students WHERE Name LIKE 'L%'; 不适用B+ TREE索引:
如果查询条件不是从最左侧列开始,索引无效;
index(age,Fname), WHERE Fname='Jerry';(无效) , WHERE age>30 AND Fname='Smith';
不能跳过索引中的某列;
index(name,age,gender)
WHERE name='black' and age > 30;
WHERE name='black' AND gender='F'; (无效不可用)
如果查询中的某个列是为范围查询,那么其右侧的列都无法再使用索引优化查询;
WHERE age>30 AND Fname='Smith' (无效) Hash索引:基于哈希表实现,特别适用于值的精确匹配查询; 适用场景:
只支持等值比较查询,例如=, IN(), <=> 不用场景:
所有非精确值查询;MySQL仅对memory存储引擎支持显式的hash索引; 索引优点:
降低需要扫描的数据量,减少IO次数;
可以帮助避免排序操作,避免使用临时表;
帮助将随机IO转为顺序IO; 高性能索引策略:
(1) 在WHERE中独立使用列,尽量避免其参与运算;
WHERE age+2 > 32 ; (索引失效)
(2) 左前缀索引:索引构建于字段的最左侧的多少个字符,要通过索引选择性来评估
索引选择性:不重复的索引值和数据表的记录总数的比值;
(3) 多列索引:
AND连接的多个查询条件更适合使用多列索引,而非多个单键索引;
(4) 选择合适的索引列次序:选择性最高的放左侧; EXPLAIN来分析索引有效性: EXPLAIN [explain_type] SELECT select_options 分析select语句索引的有效性 explain_type:
EXTENDED
| PARTITIONS 输出结果:
id: 1
select_type: SIMPLE
table: students
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra: id:当前查询语句中,第个SELECT语句的编号; 复杂的查询的类型主要三种:
简单子查询
用于FROM中的子查询
联合查询 注意:联合查询的分析结果会出现一个额外的匿名临时表; select_type:查询类型:
简单查询:SIMPLE
复杂查询:
简单子查询:SUBQUERY
用于FROM中的子查询:DERIVED
联合查询中的第一个查询:PRIMARY
联合查询中的第一个查询之后的其它查询:UNION
联合查询生成的临时表:UNION RESULT table:查询针对的表; type:关联类型,或称为访问类型,即MySQL如何去查询表中的行
ALL:全表扫描;
index:根据索引的顺序进行的全表扫描;但同时如果Extra列出现了"Using index”表示使用了覆盖索引;
range:有范围限制地根据索引实现范围扫描;扫描位置始于索引中的某一项,结束于另一项;
ref:根据索引返回的表中匹配到某单个值的所有行(匹配给定值的行不止一个);
eq_ref:根据索引返回的表中匹配到某单个值的单一行,仅返回一个行,但需要与某个额外的参考值比较,而不是常数;
const,system:与某个常数比较,且只返回一行; possiable_keys:查询中可能会用到的索引; key:查询中使用的索引; key_len:查询中用到的索引长度; ref:在利用key字段所显示的索引完成查询操作时所引用的列或常量值; rows:MySQL估计出的为找到所有的目标项而需要读取的行数; Extra:额外信息
Using index:使用了覆盖索引进行的查询;
Using where:拿到数据后还要再次进行过滤;
Using temporary:使用了临时表以完成查询;
Using filesort:对结果使用了一个外部索引排序;

实战:

数据库中插入大量数据,从而创建索引

[root@danran ~]# for i in {5..1000};do mysql -e "INSERT INTO mydb.students VALUES ('$i','stu$i',$[$RANDOM%100+1],'F','major$i')";done
[root@danran ~]# for i in {1001..2000};do mysql -e "INSERT INTO mydb.students VALUES ('$i','stu$i',$[$RANDOM%100+1],'M','major$i')";done

单键索引

MariaDB [(none)]> create database mydb;  创建数据库
MariaDB [(none)]> use mydb;
MariaDB [mydb]> create table students (stuid INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,name VARCHAR(200),age TINYINT UNSIGNED,gender ENUM('F','M'),major VARCHAR(200));
创建students表,子段为stuid,name,age,gender,major
MariaDB [mydb]> INSERT INTO students (name,age,gender,major) VALUE('dan',16,'M','jian'),('ran',20,'F','quan'),('jevon',19,'M','qiang'),('wei',15,'F','wu die');
插入数据到students表
MariaDB [mydb]> EXPLAIN SELECT name,age FROM students WHERE age >=15; 分析select语句索引的有效性
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 1819 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
MariaDB [mydb]> HELP CREATE INDEX 查看索引创建帮助 创建索引
MariaDB [mydb]> CREATE INDEX name ON students(name); \\根据students表的name字段创建索引name 显示students表的索引信息
MariaDB [mydb]> SHOW INDEXES FROM students;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| students | 0 | PRIMARY | 1 | stuid | A | 2203 | NULL | NULL | | BTREE | | |
| students | 1 | name | 1 | name | A | 244 | NULL | NULL | YES | BTREE | | |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 显示select语句的索引有效性
MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE name = 'stu1002';
+------+-------------+----------+------+---------------+------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-----------------------+
| 1 | SIMPLE | students | ref | name | name | 203 | const | 1 | Using index condition |
+------+-------------+----------+------+---------------+------+---------+-------+------+-----------------------+ 显示select语句等值查询的索引有效性
MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE name = 'stu100%';
+------+-------------+----------+------+---------------+------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-----------------------+
| 1 | SIMPLE | students | ref | name | name | 203 | const | 1 | Using index condition |
+------+-------------+----------+------+---------------+------+---------+-------+------+-----------------------+ 显示select语句范围查询的索引有效性
MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE name LIKE 'stu100%';
+------+-------------+----------+-------+---------------+------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+------+---------+------+------+-----------------------+
| 1 | SIMPLE | students | range | name | name | 203 | NULL | 11 | Using index condition |
+------+-------------+----------+-------+---------------+------+---------+------+------+-----------------------+

多键索引

创建多键索引
MariaDB [mydb]> CREATE INDEX name_and_age ON students(name,age); 根据students表的name和age字段创建name_and_age多键索引 显示students表的索引信息,其中包含name单键索引和name_and_age多键索引
MariaDB [mydb]> SHOW INDEXES FROM students;
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| students | 0 | PRIMARY | 1 | stuid | A | 1765 | NULL | NULL | | BTREE | | |
| students | 1 | name_and_age | 1 | name | A | 160 | NULL | NULL | YES | BTREE | | |
| students | 1 | name_and_age | 2 | age | A | 160 | NULL | NULL | YES | BTREE | | |
| students | 1 | name | 1 | name | A | 160 | NULL | NULL | YES | BTREE | | |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 有多键索引使用时,单键索引失效
MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE name LIKE 'stu100%';
+------+-------------+----------+-------+-------------------+------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+-------------------+------+---------+------+------+-----------------------+
| 1 | SIMPLE | students | range | name,name_and_age | name | 203 | NULL | 11 | Using index condition |
+------+-------------+----------+-------+-------------------+------+---------+------+------+-----------------------+ 删除单键name索引
MariaDB [mydb]> DROP INDEX name ON students; 删除单键name索引后,name_and_age多键索引依然存在
MariaDB [mydb]> SHOW INDEXES FROM students;
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| students | 0 | PRIMARY | 1 | stuid | A | 1630 | NULL | NULL | | BTREE | | |
| students | 1 | name_and_age | 1 | name | A | 1630 | NULL | NULL | YES | BTREE | | |
| students | 1 | name_and_age | 2 | age | A | 1630 | NULL | NULL | YES | BTREE | | |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 显示select语句的有效索引为多键索引name_and_age
MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE name LIKE 'stu100%';
+------+-------------+----------+-------+---------------+--------------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+--------------+---------+------+------+-----------------------+
| 1 | SIMPLE | students | range | name_and_age | name_and_age | 203 | NULL | 11 | Using index condition |
+------+-------------+----------+-------+---------------+--------------+---------+------+------+-----------------------+ 多键索引name_and_age时,跳过name键直接使用age键时,索引无效,如下
MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE age >=50;
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 1630 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+ 多键索引name_and_age时,直接使用单键name或使用多键时,索引有效(以下因为name键过滤太过故索引无效)
MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE name LIKE 'stu%' AND age >=50;
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | name_and_age | NULL | NULL | NULL | 1630 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+ 当多键索引过滤不多时,索引可以正常使用,故key索引键值正常显示
MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE name LIKE 'stu100%' AND age >=50;
+------+-------------+----------+-------+---------------+--------------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+--------------+---------+------+------+-----------------------+
| 1 | SIMPLE | students | range | name_and_age | name_and_age | 205 | NULL | 11 | Using index condition |
+------+-------------+----------+-------+---------------+--------------+---------+------+------+-----------------------+

多表查询的索引信息

显示select语句多表查询
MariaDB [mydb]> SELECT * FROM students WHERE age = 100 UNION SELECT * FROM students WHERE name LIKE 'stu100%'; 显示select语句多表查询的有效索引信息
MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE age = 100 UNION SELECT * FROM students WHERE name LIKE 'stu100%';
+------+--------------+------------+-------+---------------+--------------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------+------------+-------+---------------+--------------+---------+------+------+-----------------------+
| 1 | PRIMARY | students | ALL | NULL | NULL | NULL | NULL | 1630 | Using where |
| 2 | UNION | students | range | name_and_age | name_and_age | 203 | NULL | 11 | Using index condition |
| NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | |
+------+--------------+------------+-------+---------------+--------------+---------+------+------+-----------------------+

等值查询的有效索引

MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE stuid=4;
+------+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | students | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+------+-------------+----------+-------+---------------+---------+---------+-------+------+-------+

范围查询的有效索引

MariaDB [mydb]> EXPLAIN SELECT * FROM students WHERE stuid IN (1,77,1200,1300);
+------+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | students | range | PRIMARY | PRIMARY | 4 | NULL | 4 | Using where |
+------+-------------+----------+-------+---------------+---------+---------+------+------+-------------+

索引显示的选项:

id:select语句的ID
select_type:查询类型:
简单查询:SIMPLE
复杂查询:
简单子查询:SUBQUERY
用于FROM中的子查询:DERIVED
联合查询中的第一个查询:PRIMARY
联合查询中的第一个查询之后的其它查询:UNION
联合查询生成的临时表:UNION RESULT
table:查询针对的表;
type:关联类型,或称为访问类型,即MySQL如何去查询表中的行
ALL:全表扫描;表示无索引可用或索引过滤的行太多似无索引过滤
index:根据索引的顺序进行的全表扫描;但同时如果Extra列出现了"Using index”表示使用了覆盖索引;
range:有范围限制地根据索引实现范围扫描;扫描位置始于索引中的某一项,结束于另一项;
ref:根据索引返回的表中匹配到某单个值的所有行(匹配给定值的行不止一个);
eq_ref:根据索引返回的表中匹配到某单个值的单一行,仅返回一个行,但需要与某个额外的参考值比较,而不是常数;
const,system:与某个常数比较,且只返回一行;
possiable_keys:查询中可能会用到的索引;
key:查询中使用的索引;
key_len:查询中用到的索引长度;
ref:在利用key字段所显示的索引完成查询操作时所引用的列或常量值;
rows:MySQL估计出的为找到所有的目标项而需要读取的行数;
Extra:额外信息
Using index:使用了覆盖索引进行的查询;
Using where:拿到数据后还要再次进行过滤;
Using temporary:使用了临时表以完成查询;
Using filesort:对结果使用了一个外部索引排序;

Mysql实战之索引的更多相关文章

  1. MySQL实战 | 04 为什么要使用索引?

    原文链接:MySQL实战 | 为什么要使用索引? 用过 MySQL 的应该都知道索引是干啥的吧,应该多少都设置过索引,但是若是问你索引是怎么实现的,你能说上来吗? 索引是什么? MySQL 官方对索引 ...

  2. Mysql实战45讲 05讲深入浅出索引(下)极客时间 读书笔记

    极客时间 Mysql实战45讲 04讲深入浅出索引(下)极客时间 笔记体会: 回表:回到主键索引树搜索的过程,称为回表覆盖索引:某索引已经覆盖了查询需求,称为覆盖索引,例如:select ID fro ...

  3. Mysql实战45讲 04讲深入浅出索引(上)读书笔记 极客时间

    极客时间 Mysql实战45讲 04讲深入浅出索引 极客时间(上)读书笔记  笔记体悟 1.索引的作用:提高数据查询效率2.常见索引模型:哈希表.有序数组.搜索树3.哈希表:键 - 值(key - v ...

  4. MySQL的InnoDB索引原理详解

    摘要 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本篇 ...

  5. MySQL的InnoDB索引原理详解 (转)

    摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本 ...

  6. mysql优化之索引优化

    Posted by Money Talks on 2012/02/23 | 第一篇 序章第二篇 连接优化第三篇 索引优化第四篇 查询优化第五篇 到实战中去 索引优化 索引优化涉及到几个方面,包括了索引 ...

  7. MySQL实战 | 06/07 简单说说MySQL中的锁

    原文链接:MySQL实战 | 06/07 简单说说MySQL中的锁 本文思维导图:https://mubu.com/doc/AOa-5t-IsG 锁是计算机协调多个进程或纯线程并发访问某一资源的机制. ...

  8. MySQL实战 | 01-当执行一条 select 语句时,MySQL 到底做了啥?

    原文链接:当执行一条 select 语句时,MySQL 到底做了啥? 也许,你也跟我一样,在遇到数据库问题时,总时茫然失措,想重启解决问题,又怕导致数据丢失,更怕重启失败,影响业务. 就算重启成功了, ...

  9. 剖析Mysql的InnoDB索引

    摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本 ...

随机推荐

  1. Android(java)学习笔记91:Eclipse中代码提示去掉@override,不然就报错!

    1. Eclipse中提示去掉@Override 把项目下载下来后有@Override的注释的方法会报错,如果把@Override去掉就不报错了.经过查阅后发现:@override注释在jdk1.5环 ...

  2. mkfs.xfs 命令找不到的解决方法

    对硬盘进行格式化: # mkfs.xfs /dev/sdb1 系统显示: mkfs.xfs error: command not found. 可能是系统不完全安装 运行 which mkfs  查看 ...

  3. convert命令

    可以修改图片的分辨率 convert -resize 600×600 src.jpg dst.jpg src.jpg是你要修改的图片的名字 dst.jpg是新生成的图片名字

  4. JSON.parse(text[, reviver])

    1. JSON.parse(text[, reviver])text 必需 有效的json字符串reviver 可选 函数 2. 举栗子1) 只有第一个参数 let objStr = '{" ...

  5. mac利用套件管理工具homebrew正确地同时安装python2.7和python3

    MAC OSX 正確地同時安裝 PYTHON 2.7 和 PYTHON3     Python3 出來了(其實已經出來很久了,暈)!但是還是有很多 library 還是使用 Python2.7,所以要 ...

  6. node 日志分割-pm2-logrotate

    使用pm2-logrotate进行pm2日志切割,测试是按照文件大小1k切割: 安装 pm2 install pm2-logrotate 设置 重启 截图 截图是按照文件大小分割,如果文件小于设置分割 ...

  7. ATM-db-dnhandler

    import os,jsonfrom conf import settings def select(name): user_path = os.path.join(settings.BASE_DB, ...

  8. js中如何把RGB颜色转换为16进制颜色

    将RGB颜色值转换为16进制颜色值,主要是将 R.G.B 值分别转换为对应的十六进制值,填入 #RRGGBB 中. 推荐在线颜色转换工具:http://www.ecjson.com/rgbhex/ 例 ...

  9. JZOJ 4269. 【NOIP2015模拟10.27】挑竹签

    4269. [NOIP2015模拟10.27]挑竹签 (File IO): input:mikado.in output:mikado.out Time Limits: 1000 ms  Memory ...

  10. 常见的js算法面试题收集,es6实现

    1.js 统计一个字符串出现频率最高的字母/数字 let str = 'asdfghjklaqwertyuiopiaia'; const strChar = str => { let strin ...