【mysql索引】之多列索引

第零步:简单说一说


多列索引并不是指建立多个单列索引,而是指在多个字段建立一个索引。

在多个列上建立独立的单列索引大部分情况下并不能提高MySQL的查询性能,MySQL在5.0之后推出了索引合并策略(index merge),一定程度上可以使用多个单列索引来定位指定的行,但实际上更多时候说明了表上的索引建的很糟糕:

1.当数据库服务器对多个单列索引做相交操作(intersection,通常伴有多个AND条件)时,通常意味着需要一个包含多个相关列的多列索引,而不是多个单列索引。
2.当数据库服务器对多个单列索引做联合操作(union,通常伴有多个OR条件)时,需要消耗大量的CPU和内存在算法缓存、排序与合并上,特别在某些索引选择性不高、且需要合并扫描并返回大量数据的时候。

3.更重要的是,优化器不会把以上的计算成本加入到查询成本之中,优化器只关心随机页面读取,这会导致查询成本被低估。


第一步:选择合适的索引顺序

这里适用于B-Tree索引,因为哈希索引并不像B-Tree那样按顺序存储。
有一个经验法则:将选择性最高的列放到索引的最前列,这个法则通常情况下有用,但通常没有避免随机IO和排序那么重要。当不需考虑排序和分组时,这个法则通常是很好的,但还需要留意的是值的分布,拿sakila数据库里的payment表举例(关于选择性和sakila这里有上一篇的链接【mysql索引】之前缀索引),查询结果如图1:
SELECT
COUNT(DISTINCT staff_id)/COUNT(*) staff_id_selectivity,
COUNT(DISTINCT customer_id)/COUNT(*) customer_id_selectivity,
COUNT(*) total
FROM payment

图1:

可以看出customer_id的选择性更高,因此应该把customer_id作为多列索引的第一项,第二项是staff_id。


第二步:添加多列索引

执行下面语句即可:
ALTER TABLE payment ADD KEY `idx_customer_id_staff_id` (customer_id, staff_id);


最后需注意的一点:

上面的经验法则对于下面的情况,需要额外的处理:
如果某个条件值得基数过大,例如一个商城网站数据库里customer表里字段username为guest(游客)的数量太大,几乎占了整个表的9/10,那么如果用索引来查询username为guest的用户时,那个索引基本上是起不了作用的,这样有可能会极大损耗服务器的性能,解决方法是在代码层面上解决,如限制查询username值为guest的用户等。





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值