Mysql索引性能优化

B-tree索引

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)

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不能索引优化查询

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 from profiles where sex=‘m’ order by rating limit 10
对于此查询,如果没有索引的话,查询会很慢,可以增加(sex,rating)索引。
如果用户翻页很多: select from profiles where sex=‘m’ order by rating limit 100000,10
即使有索引,也会很慢,此种情况可以使用覆盖索引查询返回需要的主键,然后再根据主键关联原表获取需要的行,减少Mysql扫描那些需要丢弃的行数。
select from profiles  inner join (select id from profiles where sex=‘m’ order by rating limit 100000,10 ) as x using id

 

 

 


 

 

 

 

 

你可能感兴趣的:(数据库,性能优化,mysql)