从功能逻辑上来说,分为:普通索引、唯一索引、主键索引、全文索引。
按照物理实现来分,分为:聚簇索引 和 非聚簇索引。
按照作用字段个数来分,分成:单列索引 和 联合索引。
不同的存储引擎支持的索引类型也不一样
某个字段在SELECT、UPDATE 或 DELETE 语句的 WHERE 条件中经常被使用到,那么就需要给这个字段创建索引了。尤其是在数据量大的情况下,创建普通索引就可以大幅提升数据查询的效率。
索引就是让数据按照某种顺序进行存储或检索,因此当我们使用 GROUP BY 对数据进行分组查询,或者使用ORDER BY对数据进行排序的时候,就需要对 分组 或者 排序 的字段进行索引。如果需要索引的列有多个,那么可以在这些列上建立 组合索引。
SELECT student_id, COUNT(*) AS num
FROM student_info
GROUP BY student_id
我们可以给 student_id 加上索引,提高查询速率。同样,如果是 ORDER BY,也可以给相应字段加上索引。
SELECT student_id, COUNT(*) AS num FROM student_info
GROUP BY student_id
ORDER BY create_time DESC
如果分别给 student_id 、create_time 建立索引的话,会发现实际上只会用到 student_id 的索引,并且 执行速度较慢。因为多个单列索引在多条件查询时 只会生效一个索引 (MSOL 会选择其中一个限制最严格的作为索引,所以在多条件联合查询的时候最好创建联合索引。
正常来说我们应该根据SQL执行的顺序来创建联合索引,这里由于group by先执行,所以我们应该创建的是 (student_id,create_time) 的联合索引,而非 (create_time,student_id)。这里提一下,如果(create_time,student_id) 顺序的联合索引 和 student_id 单列索引 共存的话还是会走student_id 单列索引,因为group by先执行。
有时候我们需要对某个字段进行去重,使用 DISTINCT,那么对这个字段创建索引,也会提升查询效率
我们这里所说的 类型大小 指的就是该类型表示的数据范围的大小。
这个建议对于表的 主键来说更加适用,因为不仅是聚簇索引中会存储主键值,其他所有的二级索引的节点处都会存储一份记录的主键值,如果主键使用更小的数据类型,也就意味着节省更多的存储空间和更高效的 I/O
假设我们的字符串很长,那存储一个字符串就需要占用很大的存储空间。在我们需要为这个字符串列建立索引时,会出现两个问题:
- 字符串比较速度慢
- 占用的存储空间大
我们可以通过截取字段的前面一部分内容建立索引,这个就叫前缀索引。这样在查找记录时虽然不能精确的定位到记录的位置,但是能定位到相应前缀所在的位置,然后根据前缀相同的记录的主键值回表查询完整的字符串值。既节约空间,又减少了字符串的比较时间。
计算截取不同长度的散列度(选择性)
如检测 截取地址长度 的散列度:
select count(distinct left(列名,索引长度)) / count(*) from 表;
越接近1当然效果越好,说明散列度高
列的基数 指的是某一列中不重复数据的个数。比方说某个列包含值 2,5,8,2,5,8,2,5,8,虽然有9条记录,但该列的基数却是3。也就是说,在记录行数一定的情况下,列的基数越大,该列中的值越分散;列的基数越小,该列中的值越集中。
这个列的基数指标非常重要,直接影响我们是否能有效的利用索引。因为索引的价值是帮助你快速定位,如果需要定位的数据有很多,那么索引就失去了它的使用价值,比如通常情况下的性别字段。
可以使用公式计算区分度,越接近1越好,一般超过33%就算是比较高效的索引了,所以有唯一性字段适合建立索引
select count(distinct 列名)/count(*) from 表名
这样也可以较少的建立一些索引。同时,由于"最左前缀原则",可以增加联合索引的使用率。
如果表记录太少,比如少于 1000 个,那么是不需要创建索引的。表记录太少,是否创建索引对查询效率的影响并不大。甚至说,查询花费的时间可能比遍历索引的时间还要短,索引可能不会产生优化效果。
在条件表达式中经常用到的不同值较多的列上建立索引,但字段中如果有大量重复数据,也不用创建索引。比如学生表中的性别字段,只有男和女两种值,因此无需建立索引。如果建立索引,不但不会提高查询效率,反而会严重降低数据更新速度。
在实际工作中,我们也需要注意平衡,索引的数目不是越多越好。我们需要限制每张表上的索引数量,最好单张表索引数量不超过6个。原因: