Mysql索引性能优化

B-tree索引mysql

table user(sysno,name,sex,age,city,birthday) ,创建索引index1(name),聚合索引 index2(sex,age,city)
insert into user values(1,zhangsan,1,34,shanghai,2000-03-23)
insert into user values(2,lisi,1,23,zhejiang,2001-05-23)
insert into user values(3,lishimin,1,27,shanghai,2002-01-27)
insert into user values(4,wangwu,2,21,shanghai,2004-06-11)sql

1.适合索引的场景函数

全值匹配。例 name=lisi的,  或者 sex=1 and age=23 and city=beijing
最左前缀匹配。例 sex=2的,即聚合索引的最左列
列前缀匹配。例name like a%,  或者 sex like 1%.只有索引的第一列适合此条件
精准匹配某一列并范围匹配另外一列。例name=lisi and age like 2%性能

2.索引的限制优化

索引使用必须有序。例sex=1 and city=shanghai and age =22 ,这种状况没法使用
不能跳过索引的列。例sex=1 and city=shanghai ,这种状况没法使用
若是索引中某个列范围查询,则右边全部列不能使用索引查询。例 sex=1 and age like 1% and city=beijing,city不能索引优化查询spa

3.高性能索引策略排序

3.1独立的列,即索引列不能是表达式,也不能是函数的参数。例 age+1=23, 或者nullif(city,shanghai)=beijing
3.2索引前缀和索引选择性
索引前缀,即索引很长的字符串会让索引变的大且慢,能够索引开始的部分字符,节约索引空间
索引选择性,即不重复的索引值和总记录的比值,索引选择性越高,查询效率越高。惟一索引索引选择性等于1,查询效率最好
原则:对于BLOB、TEXT、长VARCHAR的列,使用前缀索引
优势:前缀索引能使索引更小,更快
缺点:mysql不能使用前缀索引作order by 和group by
前缀索引设置的位数与全部不重复记录数的占比类似为最好
示例:
select count(distinct city)/count(*) from user;
+   0.435;索引

select count(distinct left(city,3))/count(*) as sel3,
count(distinct left(city,4))/count(*) as sel4,
count(distinct left(city,5))/count(*) as sel5,
count(distinct left(city,6))/count(*) as sel6 from user
| sel3   | sel4   | sel5   | sel6   |
+--------+--------+--------+--------+
| 0.3408 | 0.4100 | 0.4225 | 0.4300 |
sel6的值最接近完整列选择性。因此索引前缀为6最合适
alter table user add index index_city(city(6));
3.3多列索引
索引的顺序依赖于使用该索引的查询,而且同时须要考虑如何更好地知足排序和分组的须要。
在不考虑排序和分组时,将选择性高的列放在索引的最前列,根据运行频率最高的查询来适度调整索引列的顺序。
例如: select * from user where sex=1 and age=23
建立(sex,age)索引? 明显age的选择性要高,所以应建立index(age,sex)
3.4冗余和重复索引
重复索引是指在相同的列上按照相同的顺序建立的相同类型的索引。应该避免这样建立重复索引,发现之后也应该当即移除。
冗余索引是指建立了索引(A,B),再建立索引(A)就是冗余索引。将一个索引扩展为(A,ID),其中ID是主键,对于InnoDB来讲主键列已经包含在二级索引中了,因此这也是冗余的
备注:扩展索引时须要注意,例如,在列(A)上的索引就至关于在(A,ID)上的索引。若是有像WHERE A = 5 ORDER BY ID这样的查询,这个索引会颇有做用。但若是将索引扩展为(A,B),则实际上就变成了(A,B,ID),那么上面查询的ORDER BY子句就没法使用该索引作排序,而只能用文件排序了
3.5支持多种过滤条件
city和sex的选择性很低,若是使用频次较高,依然建议在建立组合索引时将(sex,city)做为前缀。若是有查询不须要sex做为条件,能够增长sex in(”1”,”2”)做为条件,知足最左前缀要求。where sex in("1","2") and city="shanghai"
若是须要用IN来知足索引查询,尽可能将IN 放到索引的后面。
3.6优化排序
select <cols> from profiles where sex=‘m’ order by rating limit 10
对于此查询,若是没有索引的话,查询会很慢,能够增长(sex,rating)索引。
若是用户翻页不少: select <cols> from profiles where sex=‘m’ order by rating limit 100000,10
即便有索引,也会很慢,此种状况能够使用覆盖索引查询返回须要的主键,而后再根据主键关联原表获取须要的行,减小Mysql扫描那些须要丢弃的行数。
select <cols> from profiles  inner join (select id from profiles where sex=‘m’ order by rating limit 100000,10 ) as x using idci