问题sql
索引能够加快查询速度,那么是否是表都须要创建索引呢?
spa
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(即当索引自己包含查询全部需所有数据时,再也不访问数据文件自己)。