MySQL-索引优化篇(1)_安装演示库 [前缀索引、联合索引、覆盖索引] explain参数
文章目录
- 生猛干货
- 官方文档
- 安装演示数据库sakila
- 索引优化策略
- 索引列上不能使用表达式或者函数
- 前缀索引和索引列的选择性
- 前缀索引的创建
- 索引列的选择性
- 前缀索引的优缺点
- 联合索引
- 如何选择索引列的顺序
- 覆盖索引
- 定义
- 优点
- 无法使用覆盖索引的情况
- 演示
- explain的几个参数的说明
- 搞定MySQL
生猛干货
带你搞定MySQL实战,轻松对应海量业务处理及高并发需求,从容应对大场面试
官方文档
https://dev.mysql.com/doc/
如果英文不好的话,可以参考 searchdoc 翻译的中文版本
http://www.searchdoc.cn/rdbms/mysql/dev.mysql.com/doc/refman/5.7/en/index.com.coder114.cn.html
安装演示数据库sakila
[root@artisan ~]# wget http://downloads.mysql.com/docs/sakila-db.tar.gz
.....
.....
.....
2020-02-01 21:31:15 (2.74 KB/s) - ‘sakila-db.tar.gz’ saved [732161/732161][root@artisan ~]# tar -xvzf sakila-db.tar.gz
sakila-db/
sakila-db/sakila-data.sql
sakila-db/sakila-schema.sql
sakila-db/sakila.mwb
[root@artisan ~]# cd sakila-db
[root@artisan sakila-db]# ls
sakila-data.sql sakila.mwb sakila-schema.sql
[root@artisan sakila-db]# mysql -uroot -p < sakila-schema.sql
Enter password:
[root@artisan sakila-db]# mysql -uroot -p < sakila-data.sql
Enter password:
[root@artisan sakila-db]#
索引优化策略
索引列上不能使用表达式或者函数
举个例子
select .... from t_order
where to_days(out_date) - to_days(current_date) < = 30
即使我们在out_date建立了 B树索引,因为使用了函数to_days,无法走索引。
那该如何改造呢? ------------> 如下
select .... from t_order
where out_date <= data_add(current_date , interval 30 day) ;
前缀索引和索引列的选择性
当索引是很长的字符序列(比如BLOB,TEXT,或者很长的VARCHAR)时,这个索引将会很占内存,而且会很慢,这时候就会用到前缀索引了。所谓的前缀索引就是去索引的前面几个字母作为索引,但是要降低索引的重复率,索引我们还必须要判断前缀索引的重复率
前缀索引的创建
创建前缀索引
create index index_name on table(col_name(n));
注意建立索引的区别 col_name(n)
这个n的长度,取悦于存储引擎
innodb 最大767个字节
myIsam 最大1000个直接
索引列的选择性
索引的选择性是指不重复的索引值和表的记录数的比值
选择性越高,查询效率越快。 因为选择性高的索引可以让MySQL在查找时过滤掉更多的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
举个例子:
有4条记录
如果前缀索引,我们创建的时候,长度设置的是2 , 那么
不重复的索引为 2 ,总记录数为4 , 索引选择性 0.5
如果设置为 3 ,则
不重复的索引为 4 ,总记录数为4 , 索引选择性1 . 此时,性能最高,因为不用过滤数据啊。
合理选择,对提高查询性能帮助很大
前缀索引的优缺点
优点:
- 前缀索引是一种能使索引更小,更快的有效办法 。
缺点:
- mysql无法使用其前缀索引做ORDER BY和GROUP BY,也无法使用前缀索引做覆盖扫描。
联合索引
如何选择索引列的顺序
经常会被使用到的列优先,放到联合索引的最左边 。
但也不是绝对的,举个例子 有个状态 state,就几个值, 选择性很差(因为根据每个state,筛选出来的数据太多了。。。)就不适合放到联合索引的最左边 ,放到了最左边,mysql也不一定使用
选择性高的列优先 。
啥叫选择性高的列? 比如根据这个列 经过筛选后,能够把大部分的数据都过滤掉,之剩下很少的数据,那么就可以把这列称为选择性高的列。
宽度小的列优先
当然了有个前提,不违反选择性。 宽度小意味着I/O 少,效率高
覆盖索引
定义
覆盖索引: 如果一个索引包含(或覆盖)所有需要查询的字段的值 ,简言之----->只需扫描索列而无须回表查非索引列的字段。
优点
可优化缓存,减少磁盘I/O操作
举个例子: 一个表 15个字段, 索引字段 3个, 我们就查询这3个索引列的值,而不用回表,查询的字段少,可以缓存更多的数据,同时从内存中获取,可以极大的减少磁盘I/O操作
可以减少随机I/O, 变随机I/O为顺序I/O操作
可以避免对Innodb主键索引的二次查询
可以避免MyISAM表进行系统调用
无法使用覆盖索引的情况
- 有些存储引擎不支持覆盖索引
- 如果查询中使用了太多的列,尤其是那种查询全部字段的,或者 select * 的
- 使用了双% 号的like查询
演示
我们用刚才导入的 sakila 数据 来演示下
select * 无法使用覆盖索引的演示:
[root@artisan sakila-db]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 63
Server version: 5.7.29-log MySQL Community Server (GPL)
.......
.......
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| artisan |
| artisanBinLog |
| data |
| mysql |
| performance_schema |
| sakila |
| sys |
+--------------------+
8 rows in set (0.01 sec)mysql> use sakila;
No connection. Trying to reconnect...
Connection id: 64
Current database: *** NONE ***Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
mysql> show tables;
+----------------------------+
| Tables_in_sakila |
+----------------------------+
| actor |
| actor_info |
| address |
| category |
| city |
| country |
| customer |
| customer_list |
| film |
| film_actor |
| film_category |
| film_list |
| film_text |
| inventory |
| language |
| nicer_but_slower_film_list |
| payment |
| rental |
| sales_by_film_category |
| sales_by_store |
| staff |
| staff_list |
| store |
+----------------------------+
23 rows in set (0.00 sec)mysql> desc film;
+----------------------+---------------------------------------------------------------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+---------------------------------------------------------------------+------+-----+-------------------+-----------------------------+
| film_id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(128) | NO | MUL | NULL | |
| description | text | YES | | NULL | |
| release_year | year(4) | YES | | NULL | |
| language_id | tinyint(3) unsigned | NO | MUL | NULL | |
| original_language_id | tinyint(3) unsigned | YES | MUL | NULL | |
| rental_duration | tinyint(3) unsigned | NO | | 3 | |
| rental_rate | decimal(4,2) | NO | | 4.99 | |
| length | smallint(5) unsigned | YES | | NULL | |
| replacement_cost | decimal(5,2) | NO | | 19.99 | |
| rating | enum('G','PG','PG-13','R','NC-17') | YES | | G | |
| special_features | set('Trailers','Commentaries','Deleted Scenes','Behind the Scenes') | YES | | NULL | |
| last_update | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+----------------------+---------------------------------------------------------------------+------+-----+-------------------+-----------------------------+
13 rows in set (0.00 sec)# 查询 索引列 language_id 重点看 Extra mysql> explain select language_id from film where language_id = 1 \G ;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: filmpartitions: NULLtype: ref
possible_keys: idx_fk_language_id -----> 可能用的索引 key: idx_fk_language_id ----------------> 实际使用的索引key_len: 1ref: constrows: 1000filtered: 100.00Extra: Using index ---------------->使用了索引,因为仅查询了索引列,这里就是覆盖索引
1 row in set, 1 warning (0.07 sec)ERROR:
No query specified# 查看执行计划 重点看 Extra mysql> explain select * from film where language_id = 1 \G ;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: filmpartitions: NULLtype: ALL ----------------------> 连接类型
possible_keys: idx_fk_language_id -----> 可用的索引key: NULL ----------------> 实际的索引key_len: NULLref: NULLrows: 1000filtered: 100.00Extra: Using where --------------------> using where:表示优化器需要通过索引回表查询数据;
1 row in set, 1 warning (0.00 sec)ERROR:
No query specifiedmysql>
在来看个例子
mysql> show create table actor \G ;
*************************** 1. row ***************************Table: actor
Create Table: CREATE TABLE `actor` (`actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,`first_name` varchar(45) NOT NULL,`last_name` varchar(45) NOT NULL,`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`actor_id`),KEY `idx_actor_last_name` (`last_name`)
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)ERROR:
No query specifiedmysql> explain select actor_id , last_name from actor where last_name = 'Joe' \G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: actorpartitions: NULLtype: ref
possible_keys: idx_actor_last_namekey: idx_actor_last_namekey_len: 182ref: constrows: 1filtered: 100.00Extra: Using index ------> using index 表示直接访问索引就足够获取到所需要的数据,不需要通过索引回表;
1 row in set, 1 warning (0.30 sec)
主键 actor_id ,默认就是索引 ,所以虽然增加了 actor_id , last_name也是索引列(创建primary key的时候肯定会创建一个unique index。),所以这个查询也是使用了覆盖索引。
explain的几个参数的说明
id: 1select_type: SIMPLEtable: actorpartitions: NULLtype: ref
possible_keys: idx_actor_last_namekey: idx_actor_last_namekey_len: 182ref: constrows: 1filtered: 100.00Extra: Using index
id
select_type: 查询中每个select子句的类型
(1) SIMPLE(简单SELECT,不使用UNION或子查询等)
(2) PRIMARY(查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)
(3) UNION(UNION中的第二个或后面的SELECT语句)
(4) DEPENDENT UNION(UNION中的第二个或后面的SELECT语句,取决于外面的查询)
(5) UNION RESULT(UNION的结果)
(6) SUBQUERY(子查询中的第一个SELECT)
(7) DEPENDENT SUBQUERY(子查询中的第一个SELECT,取决于外面的查询)
(8) DERIVED(派生表的SELECT, FROM子句的子查询)
(9) UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须重新评估外链接的第一行)
type 代表连接类型
常用的类型有: ALL, index, range, ref, eq_ref, const, system, NULL
从左到右,性能从差到好 , ALL 最差, NULL最好
ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
index: Full Index Scan,index与ALL区别为index类型只遍历索引树
range:只检索给定范围的行,使用一个索引来选择行
ref: 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件
const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system
NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。
possible_keys: 可用的索引 ,实际不一定用
keys : MyQL实际的索引
key_len: 表示索引中使用的字节数
extra (需重点关注)
1) using tempoaray : 中间使用了临时表
2) using index 表示直接访问索引就足够获取到所需要的数据,不需要通过索引回表;
3) using index condition:5.6加入 ,会先条件过滤索引,过滤完索引后找到所有符合索引条件的数据行,随后用 WHERE 子句中的其他条件去过滤这些数据行;
4) using where: 未使用索引,通过where条件过滤
搞定MySQL
MySQL-索引优化篇(1)_安装演示库 [前缀索引、联合索引、覆盖索引] explain参数相关推荐
- MySQL-索引优化篇(3)_利用索引优化锁
文章目录 生猛干货 官方文档 利用索引优化锁 为什么索引能优化锁 演示 无索引的情况 (获取不同的数据 发生了阻塞) 有索引的情况 (获取不同的数据 未阻塞) 搞定MySQL 生猛干货 带你搞定MyS ...
- MySQL-索引优化篇(4)_索引的维护
文章目录 生猛干货 官方文档 删除重复索引 删除冗余索引 检查重复和删除的索引 pt-duplicate-key-checker 查找未被使用的索引 更新索引统计信息 索引碎片整理 搞定MySQL 生 ...
- Mysql进阶优化篇01——四万字详解数据库性能分析工具(深入、全面、详细,收藏备用)
前 言 ?? 作者简介:,长跑型选手,立志坚持写10年博客,专注于java后端 ?? 专栏简介:mysql进阶,主要讲解mysql数据库进阶知识,包括索引.数据库调优.分库分表等 ?? 文章简介:本文 ...
- mysql语句优化百条_优化mysql语句
1.查询SQL尽量不要使用select *,而是select具体字段. 反例子:select * from employee; 正例子:select id,name from employee; 理由 ...
- mysql性能优化曹政_看曹政如何减少SQL请求
首先为了防止某些专业挑刺人士无限制发挥,先声明几个前提 1:索引优化是基础工作,没做好这个其他的不用提,但本文不展开此内容. 2:优化数据库查询有非常多的分支,减少SQL请求只是其中一个领域,其他分支 ...
- mysql数据库开启远程连接_安装MySQL数据库并开启远程访问
一.安装MySQL数据库 MySQL安装在系统盘下(C:\Program Files),方便系统备份. 1.双击安装程序,勾选"I accept the license terms" ...
- 【MySQL】索引原理(三):联合索引(最左前缀原则),覆盖索引,索引条件下推
准备工作,下面的演示都是基于user_innodb表: DROP TABLE IF EXISTS `user_innodb`; CREATE TABLE `user_innodb` (`id` big ...
- python下载numpy库_安装numpy库
1.先安装pip: 下载地址:http://pypi.python.org/pypi/pip#downloads 下载pip-8.1.2.tar.gz(md5,pgp)完成之后,解压到一个文件夹,cm ...
- mysql 删除多余帐号_安装完mysql数据库后的优化(删除多余用户和数据库)
安装完mysql数据库后的优化(删除多余用户和数据库) 发布时间:2020-06-27 19:09:35 来源:51CTO 阅读:2761 作者:冰冻vs西瓜 栏目:数据库 1.查看数据库的版本信息: ...
最新文章
- mysql导入数据io异常_mysql 数据同步 出现Slave_IO_Running:No问题的解决方法小结
- php 使用curl模拟登录discuz以及模拟发帖
- html鼠标悬停出现新元素,CSS:我如何将鼠标悬停在一个元素上,并显示另一个元素?...
- flutter 按钮_flutter好用的轮子推荐二-点赞按钮动画
- java mina 长连接_apache mina 长连接
- linux命令:返回上一次目录
- 五十、简单的斗鱼分析案例
- 第八章:Java_泛型
- oracle job 与存储过程,应用oracle job和存储过程
- MySQL 优化 —— SQL优化概述(优化专题开篇词)
- 【面试】iOS 开发面试题(二)
- 修改wifi密码后连接不上服务器,WiFi修改密码后,手机电脑连接不上
- 无限服务器不装显卡能用吗,云服务器能装显卡吗
- Win10 SAS9.4缺少增强型编辑器
- 人工智能时代都需要哪些数学知识?这些经典教材给你划重点
- 杰里之AC897N_AD697N_earphone_release_ V2.0.1 开立体声左右声道数据对调【篇】
- WIN7下安装IIS
- 不使用设备管理器卸载外设驱动的方法(转)
- @interface List
- RSA+AES混合加密实例
热门文章
- android 之DatePicker以及TimePicker的用法
- tp5备份mysql_tp5备份数据库
- 用户画像-撸一部分代码啊
- 论文笔记:Autoregressive Tensor Factorizationfor Spatio-temporal Predictions
- torch_geometric 笔记:TORCH_GEOMETRIC.UTILS(更新中)
- MATLAB中简单的数据库操作
- capcreatecapturewindowa 说明_家长不批改作业,还需要写情况说明?
- 新手入门深度学习 | 目录
- Python3 实现批量图像数据增强(扩增)并复制xml标签文件【目标检测笔记】
- curl请求模拟post发送json