Mysql实战之索引
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实战之索引的更多相关文章
- MySQL实战 | 04 为什么要使用索引?
原文链接:MySQL实战 | 为什么要使用索引? 用过 MySQL 的应该都知道索引是干啥的吧,应该多少都设置过索引,但是若是问你索引是怎么实现的,你能说上来吗? 索引是什么? MySQL 官方对索引 ...
- Mysql实战45讲 05讲深入浅出索引(下)极客时间 读书笔记
极客时间 Mysql实战45讲 04讲深入浅出索引(下)极客时间 笔记体会: 回表:回到主键索引树搜索的过程,称为回表覆盖索引:某索引已经覆盖了查询需求,称为覆盖索引,例如:select ID fro ...
- Mysql实战45讲 04讲深入浅出索引(上)读书笔记 极客时间
极客时间 Mysql实战45讲 04讲深入浅出索引 极客时间(上)读书笔记 笔记体悟 1.索引的作用:提高数据查询效率2.常见索引模型:哈希表.有序数组.搜索树3.哈希表:键 - 值(key - v ...
- MySQL的InnoDB索引原理详解
摘要 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本篇 ...
- MySQL的InnoDB索引原理详解 (转)
摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本 ...
- mysql优化之索引优化
Posted by Money Talks on 2012/02/23 | 第一篇 序章第二篇 连接优化第三篇 索引优化第四篇 查询优化第五篇 到实战中去 索引优化 索引优化涉及到几个方面,包括了索引 ...
- MySQL实战 | 06/07 简单说说MySQL中的锁
原文链接:MySQL实战 | 06/07 简单说说MySQL中的锁 本文思维导图:https://mubu.com/doc/AOa-5t-IsG 锁是计算机协调多个进程或纯线程并发访问某一资源的机制. ...
- MySQL实战 | 01-当执行一条 select 语句时,MySQL 到底做了啥?
原文链接:当执行一条 select 语句时,MySQL 到底做了啥? 也许,你也跟我一样,在遇到数据库问题时,总时茫然失措,想重启解决问题,又怕导致数据丢失,更怕重启失败,影响业务. 就算重启成功了, ...
- 剖析Mysql的InnoDB索引
摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本 ...
随机推荐
- Hbase各种查询总结
运用hbase好长时间了,今天利用闲暇时间把Hbase的各种查询总结下,以后有时间把协处理器和自定义File总结下. 查询条件分为: 1.统计表数据 2,hbase 简单分页 3,like 查询 4 ...
- solr数据分片相关
solr操作url 使用正常的core,使用命令生成coillection solr create_collection -c students2 -d ../server/solr/my/conf ...
- CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第四节
了解和使用共享内存(1) Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多个国家级的实验室进行大型并行运 ...
- CXF学习记录
1 apache CXF入门 1.1 下载 官网:cxf.apache.org 下载CXF的开发包: Apache CXF = Celtix + Xfire 支持多种协议: SOAP1.1,1.2 X ...
- Bootstrap历练实例:警告框(Alert)插件的方法
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- linux系统串口编程实例
在嵌入式开发中一些设备如WiFi.蓝牙......都会通过串口进行主机与从机间通信,串口一般以每次1bit位进行传输,效率相对慢. 在linux系统下串口的编程有如下几个步骤,最主要的是串口初始化! ...
- pytthon + Selenium+chrome linux 部署
1,centos7 安装 google-chrome (1) 添加chrome的repo源 vi /etc/yum.repos.d/google.repo [google] name=Google-x ...
- Shell脚本使用汇总整理——mysql数据库5.7.8以前备份脚本
Shell脚本使用汇总整理——mysql数据库5.7.8以前备份脚本 Shell脚本使用的基本知识点汇总详情见连接: https://www.cnblogs.com/lsy-blogs/p/92234 ...
- eclipse中使用git上传项目
eclipse中使用git上传项目 先需要上传到本地仓库 先找到此选项打钩 再如下 再添加的属性则可以自动填充邮箱和密码 之后 右键选择import 点击找到git 选中 下一步 如果没有找到git ...
- 正则表达式-基础知识Review
正则表达式(Regular Expression)是计算机科学的一个概念. 正则表达式使用单个字符窜来描述.匹配一系列符合某个句法规则的字符窜. 在很多文本编辑器里, 正则表达式通常用来被检索替换哪些 ...