Mysql索引优化一索引类型索引策略
上一篇已经讲了索引的基本类型,这一篇主要介绍下如何选择更高效的索引类型。 独立的列现在有下面一张学生成绩表 CREATE TABLE `student` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `first_name` varchar(20) NOT NULL, `last_name` varchar(20) NOT NULL, `created_at` timestamp NOT NULL, `updated_at` timestamp NOT NULL, `score` int(3) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `created_at` (`created_at`) KEY `score` (`score`)) ENGINE=InnoDB DEFAULT CHARSET=utf8现在我们要根据学生成绩查询学生姓名,这是一个很简单的查询。select first_name,last_name from student where score=99;这条sql就使用到了索引score。但是我们通常会看到很多查询不恰当的使用到索引,最后就导致mysql没办法使用到索引。如果查询中的不是独立的,则Mysql不会使用到索引,独立的列是指索引列不能是表达式的一部分,也不能是函数的参数。如select first_name,last_name from student where score+1=100;这个查询是不能使用到索引的。再如:select first_name from student where TO_DAYS(NOW())-TO_DAYS(created_at)>0;也是不能使用到索引的。 前缀索引有时候需要索引的列是很长的字符串,如果直接创建索引会使索引变的很大这样就变的比较慢了。改进方式现在能想到就是前面说到的哈希索引,但是有时候哈希索引是不适合的。这个时候就有了前缀索引:把列开始的部分字符串作为索引,这样可以大大的节约索引空间,从而提高索引效率。但这样也会降低索引的选择性。索引选择性指:不重复的索引值和数据表总数的比值。索引的选择性越高,那么索引的查询效率越高。唯一索引的选择性最高为1,性能也是最好的。对于很长的VARCHAR,TEXT这样的列,如果要作为索引的话,那么必须使用前缀索引。那么怎么选择合适的前缀索引呢。诀窍在于要选择足够长的前缀以保证比较高的索引选择性,同时又不能太长,因为索引越短,索引空间越小。如:一张订单表,要为联系人手机号做前缀索引,这个适合需要分析多少长度的前缀索引,可以查询每个长度的 SELECT COUNT(DISTINCT LEFT(phone,3))/COUNT(*) AS pre3,COUNT(DISTINCT LEFT(phone,4))/COUNT(*) AS pre4,COUNT(DISTINCT LEFT(phone,5))/COUNT(*) AS pre5,COUNT(DISTINCT LEFT(phone,6))/COUNT(*) AS pre6,COUNT(DISTINCT LEFT(phone,7))/COUNT(*) AS pre7,COUNT(DISTINCT LEFT(phone,8))/COUNT(*) AS pre8 FROM orders;+--------+--------+--------+--------+--------+--------+| pre3 | pre4 | pre5 | pre6 | pre7 | pre8 |+--------+--------+--------+--------+--------+--------+| 0.0026 | 0.0216 | 0.1397 | 0.3274 | 0.4533 | 0.4533 |+--------+--------+--------+--------+--------+--------+1 row in set (0.10 sec)可以看到在长度为7的时候,选择性的提升已经很小了。这个时候,我们就可以考虑取7这个值了。当然这里只是一个举例,在实际场景中,手机号的长度完全可以直接作为普通索引的。前缀索引是比较小而且快,但是Mysql不能用前缀索引作为group by 和order by,也不能做覆盖扫描(所以查询必须回表)。 ...