MySQL 索引选择性与前缀索引(示例库)

问题sql

索引能够加快查询速度,那么是否是表都须要创建索引呢?
spa

MySQL 索引选择原则分析(一)中已经介绍了,索引文件是存储在磁盘上的。所以索引虽然加快了查询速度,可是索引也是有代价的。

1、表记录比较少时,不必创建索引。
.net

2、索引的选择性比较低时,不必创建索引。code

索引的选择性是指不重复的索引值与表记录数的比值。
blog

索引的选择性的取值范围为(0,1】,选择性越高的索引价值越大。
索引

如:MySQL示例库的titles表,看一下它的选择性:get

SELECT COUNT(DISTINCT(title))/COUNT(1) AS Selectivity FROM titles;

title的选择性为0.0000,因此没有必要为其单独建索引。
it

3、前缀索引
ast

前缀索引是用列的前缀代替整个列做为索引key,当前缀长度合适时,能够作到既使得前缀索引的选择性接近全列索引,同时由于索引key变短而减小了索引文件的大小和维护开销。
class

下面以employees表为例介绍前缀索引的选择和使用。

SELECT * FROM employees WHERE first_name='Eric' AND last_name='Anido';

执行上面的SQL,时间为0.235s。

上面的SQL查询查询计划,能够看出,type为ALL,也就是全表扫描。

建<first_name>或<first_name,last_name>,看下两个索引的选择性:

SELECT COUNT(DISTINCT(first_name))/COUNT(1) AS Selectivity FROM employees;
SELECT COUNT(DISTINCT(CONCAT(first_name, last_name)))/COUNT(1) AS Selectivity FROM employees;

2句SQL的结果分别为0.004二、0.9313。<first_name,last_name>索引的选择性很好,可是长度为30,有没有兼顾长度和选择性的办法呢?也就是能够考虑用first_name和last_name的前几个字符创建索引,看一下选择性是多少:

SELECT COUNT(DISTINCT(CONCAT(first_name, LEFT(last_name, 3))))/COUNT(1) AS Selectivity FROM employees;
SELECT COUNT(DISTINCT(CONCAT(first_name, LEFT(last_name, 4))))/COUNT(1) AS Selectivity FROM employees;

查询2个SQL的结果分别为0.787九、0.9007,明显第二句SQL的选择性高出不少。

咱们来创建索引:

ALTER TABLE employees ADD INDEX `first_name_last_name4` (first_name, last_name(4));

查询前面的SQL语句,执行时间为0.002。查询效率已经很明显了。

总结:

前缀索引兼顾索引大小和查询速度,可是其缺点是不能用于ORDER BY和GROUP BY操做,也不能用于Covering index(即当索引自己包含查询全部需所有数据时,再也不访问数据文件自己)。

相关文章
相关标签/搜索