索引分类
1.单列索引:即一个索引只包含单个列,一个表可以有多个单列索引
2.唯一索引:索引列的值必须唯一,但允许有空值
3.复合索引:即一个索引包含多个列
创建、查看、删除、修改索引
创建索引
create index idx_city_name on city(name);
create index idx_city_name_email_status on city(name,email,status);
查看索引
show index from city;
删除索引
drop index idx_city_name on city;
alter命令
alter table city add primary key(id) 添加主键索引
alter table city add unique idx_city_name(name) 创建唯一索引
alter table city add index idx_city_name(name) 添加普通索引,索引值可以出现多次
alter table city add fulltext idx_city_name(name) 指定索引为fulltext,用于全文索引
explian 分析语句
1、id select查询的序列号,是一组数字,表示的是查询中执行select子句或者是操作表的顺序。
2、select_type 表示select的类型
simple(简单表,既不使用表连接或者子查询)
primary(查询中若包含任何复杂的子查询,最外层查询标记为该标识)
subquery(在select或where列表中包含了子查询)
derived(在from列表中包含了子查询,被标记为derived(衍生)mysql会递归执行这些子查询, 把结果放在临时表中)
UNION(若第二个select出现在union之后,则标记为union;若union包含在from子句的子查询中,外层select将被标记为:derived)
union result (从union表获取结果的select)
3、table 输出结果集的表
4、type 表示表的连接类型,性能由好到差的连接类型为(system—>const—->eq_ref—->ref—->ref_or_null—>index_merge—>index_subquery—>range—>index—>all)
null mysql不访问任何表,索引,直接返回结果
system 表只有一行记录(等于系统表),这是const类型的特列,一般不会出现
const 表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据,所以很快。如将主键置于where列表中,mysql就能将该查询转换为一个常量。const于将“主键”或“唯一”索引的所有部分与常量值进行比较
eq_ref 类似ref,区别在于使用的是唯一索引,使用主键的关联查询,关联查询出的记录只有一条。常见于主键或唯一索引扫描
ref 非唯一索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,返回所有匹配某个单独值的所有行(多个)
range 值检索给定返回的行,使用一个索引来选择行。where之后出现between,<,>,in等操作。
index index与all的区别为index类型只是遍历了索引树,通常比ALL快,ALL是遍历数据文件。
all 将遍历全表以找到匹配的行
5、possible_keys* 表示查询的时候,可能使用的索引
6、key 表示实际使用的索引
7、key_len索引字段的长度
8、rows 扫描行的数量
9、extra 执行情况的说明和描述
using-filesort 说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取,称为“文件排序”
using temporary 使用了临时表保存中间结果,mysql在对查询结果排序时使用临时表。常见于order by 和group by
using index 表示相应的select操作使用了覆盖索引,避免访问表的数据行,效率不错。
show profile 分析sql
mysql从5.0.37版本开始增加对show profiles和show profile语句的支持。show profiles能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。
select @@have_profiling;
通过have_profiling参数,能够看到当前MYSQL是否支持profile:
select @@profiling;查看是否开启
默认profiling是关闭的,可以通过set语句在session级别开启profiling;
set profiling =1;开启profiling开关;
show profiles;查看sql
show profilie for query 1;分析id为1的sql
sending data状态表示mysql线程开始访问数据行并把结果返回给客户端,而不仅仅是返回给客户端。由于在sending data状态下,mysql线程往往需要做大量的磁盘读取操作,所以经常是整个查询中耗时最长的状态。
show profilie cup for query 1;
1.status sql语句执行的状态
2.duration sql执行过程中每一个步骤的耗时
3.cpu_user
4.cpu_system
trace分析优化器执行计划
mysql5.6提供了对SQL的跟踪trace,通过trace文件能够进一步了解为什么哟花钱选择A计划而不是B计划。
打开trace,设置格式为JSON,并设置trace最大能够使用的内存大小,避免解析过程中因为默认内存过小而不能够完整展示。
set optimizer_trace="enabled=on",end_markers_in_json=on;
set optimizer_trace_max_mem_size=1000000;
执行sql语句
select * from A where age < 5
最后检查information_schema.optimizer_trace就可以知道mysql是如何执行SQL的
select * from information_schema.optimizer_trace\G;
复合索引索引失效
1.不满足最左匹配原则
2.范围索引列没有放在最后(这里的最后是说复合索引的最后,不是where条件的最后)
3.使用了select *
4.索引列上有计算
5.索引列上使用了函数
6.字符类型没加引号,底层在隐式转换
7.用is null和is not null没注意字段是否允许为空
如果字段不允许为空,则is null 和 is not null这两种情况索引都会失效。
如果字段允许为空,则is null走 ref 类型的索引,而is not null走 range 类型的索引。
8.like查询左边有%
9.使用or关键字 ,如果有一边条件不是索引,那么索引失效,使用union替代
10.not in 在mysql5.7索引会失效,mysql5.8使用range类型索引,外表大而子表小时,IN的效率更高,而外表小,子表大时,EXISTS的效率更高,若两表差不多大,则差不多。
11.<> != 在mysql5.7索引会失效,mysql5.8使用range类型索引 使用大于小于替代不等于
12.mysql 通过索引扫描的行记录数超过全表的10%~30% 左右,优化器也可能不会走索引,自动变成全表扫描。
13.有没有使用索引跟 where 后面的条件有关,而跟 order by 后面的字段没关系 ,而需不需要按文件重排序,则跟 order by 后面的字段有直接关系
单列索引和复合索引使用选择
尽量使用复合索引,而少使用单列索引。
创建复合索引
create index idx_name_sta_address on tb_seller(name,status,address);
就相当于创建了三个索引:
name
name + status
name + status +address
创建单列索引
create index idx_seller_name on tb_seller(name);
create index idx_seller_status on tb_seller(status);
create index idx_seller_address on tb_seller(address);
数据库会选择一个最优的索引来使用,并不会使用全部索引。
查看索引使用情况
show status like 'handler_read%'; 查看当前会话的索引使用情况
show global status like 'handler_read%'; 查看全局的索引使用情况
主键索引上才有数据,其他索引没有数据,只有主键的id。
除了主键索引,其他索引都是保存一个主键的id,然后根据主键的id去主键索引上找数据。
索引下推
在mysql5.6之前,复合索引会根据第一个条件找到对应的页,然后把那一页的主键id查出来,根据主键id一次次回表,再把数据全部查出来,然后再进行第二个第三个条件查询。
在mysql5.6之后,引入了索引下推,复合索引会根据第一个条件找到对应的页,然后再根据条件过滤,过滤后的结果,找到对应的主键id,再用主键id找到具体数据。
对varchar类型进行建索引的时候,长度可以先用left(列名,n)来计算多次,因为varchar(20)可能有的数据长度为4 有的数据长度为20,没有必要对全部数据进行存储。
转自:https://www.cnblogs.com/yexuba/p/16309649.html