高性能索引策略一
高效的选择和使用索引有很多方式,有的是针对特殊案例的优化方法,有的则是针对特定行为的优化,使用哪个索引,以及如何评估选择不同索引的性能影响的技巧,则需要持续不断地学习。(本文章需要一定索引基础)
1.索引要是独立的列
“独立的列”是指索引列不能是表达式的一部分,也不能是函数的参数。例如,下面这个查询无法使用actor_id列的索引
mysql>SELECT actor_id FROM sakila.actor WHERE actor_id + 1 = 5;
凭肉眼很容易看出WHERE中的表达式其实等价与 actor_id = 4,但是MySQL无法自动解析这个方程式。这完全是用户行为。我们应该养成简化WHERE条件的习惯,始终将索引列单独放在比较符号的一侧
下面是另一个常见的错误:
mysql>SELECT ... WHERE TO_DAYS(CURRENT_DATE) - TO_DAYS(date_col) <= 10;
2.前缀索引和索引的选择性
索引的选择性:
索引的选择性是指 不重复的索引值(也称之为基数)和数据表记录总数(#T)的比值,范围从1/#T到1之间。索引的选择性越高则查询效率越高。唯一索引的选择性是一,这是最好的索引选择性,性能也是最好的。
对于BLOB、TEXT或者很长的VARCHAR类型的列。必须使用前缀索引,因为mysql不允许索引这些列的完整长度。
前缀索引选择前缀长度的诀窍在于选择足够长的前缀以保证较高的选择性,通知用不能太长(以便节约空间),足够长的长度以使得前缀索引的选择性接近于索引的整个列
如何计算合适的前缀长度?
计算整列的选择性,并使前缀的选择性接近完成列的选择性
计算完整列的选择性
mysql>SELECT COUNT(DISTINCT city)/COUNT(*) city_demo;
计算不同前缀长度的选择性:
mysql>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,
COUNT(DISTINCT LEFT(city, 7))/COUNT(*) AS sel7,
FROM city_demo;
求出的前缀选择性接近于完整列的选择性基本上就可以用了,但要注意,只看平均选择性是不够的,也有例外的情况需要考虑最坏情况下的选择性。
前面已经说明如何找到合适的前缀长度,下面掩饰一下如何创建前缀索引
mysql>ALTER TABLE city_demo ADD KEY (city(7));