MySQL索引之单列索引

前提:根据反馈,需要优化查询速度比较慢的sql,架构师聊到组合索引。为了扩展知识,下载了《高性能MySQL》pdf及时充电一下奋斗


1.概念

单列索引:即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引;


2.多个单列索引


1.当查询where条件只有一个时,完全可以利用单列索引,因为这样速度可能会提高;

2.当涉及到的业务需要经常查询多个组合列,不要分别基于单个列建立多个单列索引(why?)

  原因:因为就算有多个单列索引,mysql也只会选择其中那个它认为最有效率的单列索引.


举例:表名及表结构(PlanDoctorID:值班医生ID)


添加测试索引:

ALTER TABLE `table_name` ADD INDEX `index_name` ( `column` );//或者直接在navicat添加

>mysql执行计划详解.


分别在PlanDoctorID、DepartID添加索引:


查看执行sql的执行计划,可见mysql只选择走PlanDoctorID的索引:


3.前缀索引和索引选择性


   当涉及到大且慢的索引,通常可以索引开始的部分字符,这样可以大大的节约索引空间,从而提高索引效率.但是会降低索引的选择性.

   索引选择性:不重复的索引(基数)和数据表的记录总数(#T)的比值,范围1/#T - 1.

  (注:索引的选择性越高则查询效率越高,因为选择性高的索引可以让MySQL在查找时过滤掉更多的行.)


   一般情况下某个列前缀的选择性也是足够高,也是足以满足查询性能.对于BLOB、TEXT或很长的Varchar类型的列,必须使用前缀索引,因为MySQL不允许索引这些列的完整长度.

      诀窍在于要选择足够长的前缀保证较高的选择性,同时又不能太长(以便节约空间),那如何决定前缀的合适长度呢?


使用如下的sql去计算某个字段完整列的选择性:

select count(distinct [column]) / count(*) as lenFull from [tableName]

使用如下的sql去计算某长度的前缀索引的选择性:
    

select count(distinct left ([column], 4)) / count(*) as len4 ,   
 count(distinct left ([column], 5)) / count(*) as len5 ,  
 count(distinct left ([column], 6)) / count(*) as len6 ,  
 count(distinct left ([column], 7)) / count(*) as len7 ,  
 count(distinct left ([column], 8)) / count(*) as len8 from [tableName]

示例:

城市列表测试数据:


3.1 先计算出 city 完整列的选择性:

3.2 计算出不同长度的前缀索引的选择性:


查询显示当前缀长度到达7的时候,再增加前缀长度,选择性提升的幅度已经很小了。

但只看平均选择性是不够的,也有例外的情况,需要考虑最坏情况下的选择性。平均选择性会让你认为前缀长度为4或者5的索引已经足够了,但如果数据分均很不均匀,可能就会有陷阱。如果观察前缀为4的最长出现城市的次数,可以看到明显不均匀:

如果前缀是4个字节,则最常出现的前缀的出现次数比最常出现的城市的出现次数要大的很多。即这些之的选择性比平均选择性要低。

前缀索引是一种能是索引更小、更快的有效办法,但另一方面的缺点:MySQL无法使用前缀索引做order by 和group by,也无法使用前缀索引做覆盖扫描。



参考:《高性能MySQL》.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值