前言
提起优化 SQL,你可能会把它理解为优化索引。简单来说这也不算错,索引在 SQL 优化中占了很大的比重。索引用得好,可以将 SQL 查询的效率提升 10 倍甚至更多。但在有些情况下,创建索引反而会降低效率。
本篇解决两个问题
- 什么情况下创建索引,什么时候不需要索引?
- 索引的种类有哪些?
索引是万能的吗?
索引就是帮助数据库管理系统高效获取数据的数据结构。
如果我们不使用索引,就必须从第 1 条记录开始扫描,直到把所有的数据表都扫描完,才能找到想要的数据。既然如此,如果我们想要快速查找数据,就只需要创建更多的索引就好了。其实索引不是万能的,在有些情况下使用索引反而会让效率变低。
- 在数据表中的数据行数比较少的情况下,比如不到 1000 行,不需要创建索引。
- 当数据重复度大,比如高于 10% 的时候,也不需要对这个字段使用索引。比如想要在 100 万行数据中查找其中的 50 万行(比如性别为男的数据),一旦创建了索引,你需要先访问 50 万次索引,然后再访问 50 万次数据表,这样加起来的开销比不使用索引可能还要大。
索引的种类有哪些?
按功能逻辑划分
从功能逻辑上说,索引主要有 4 种,分别是普通索引、唯一索引、主键索引和全文索引。
- 普通索引是基础的索引,没有任何约束,主要用于提高查询效率。
- 唯一索引就是在普通索引的基础上增加了数据唯一性的约束,在一张数据表里可以有多个唯一索引。
- 主键索引在唯一索引的基础上增加了不为空的约束,也就是 NOT NULL+UNIQUE,一张表里最多只有一个主键索引。 这是由主键索引的物理实现方式决定的,因为数据存储在文件中只能按照一种顺序进行存储。但可以有多个普通索引或者多个唯一索引。
- 全文索引用的不多,MySQL 自带的全文索引只支持英文。我们通常可以采用专门的全文搜索引擎,比如 ES(ElasticSearch) 和 Solr。
按物理实现划分
按照物理实现方式,索引可以分为 2 种:聚集索引和非聚集索引。我们也把非聚集索引称为二级索引或者辅助索引。
聚集索引可以按照主键来排序存储数据,这样在查找行的时候非常有效。也就是说索引和数据是一起的。
非聚集索引:数据库系统会有单独的存储空间存放非聚集索引,即有单独的索引表。索引表只存索引,不存储索引指向的数据。 也就是说系统会进行两次查找,第一次先找到索引,第二次找到索引对应的位置取出数据行。
使用聚集索引的时候,数据的查询效率高,但如果对数据进行插入,删除,更新等操作,效率会比非聚集索引低。
对 WHERE 子句的字段建立索引,可以大幅提升查询效率。
采用聚集索引进行数据查询,比使用非聚集索引的查询效率略高。如果查询次数比较多,还是尽量使用主键索引进行数据查询。
按字段个数划分
索引还可以按照字段个数进行划分,分成单一索引和联合索引。索引列为一列时为单一索引;多个列组合在一起创建的索引叫做联合索引。
创建联合索引时,我们需要注意创建时的顺序问题,因为联合索引 (x, y, z) 和 (z, y, x) 在使用的时候效率可能会存在差别。
这里需要说明的是联合索引存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。比如刚才举例的 (x, y, z),如果查询条件是 WHERE x=1 AND y=2 AND z=3,就可以匹配上联合索引;如果查询条件是 WHERE y=2,就无法匹配上联合索引。
总结
使用索引可以帮助我们从海量的数据中快速定位想要查找的数据,不过索引也存在一些不足,比如占用存储空间、降低数据库写操作的性能等,如果有多个索引还会增加索引选择的时间。当我们使用索引时,需要平衡索引的利(提升查询效率)和弊(维护索引所需的代价)。
在实际工作中,我们还需要基于需求和数据本身的分布情况来确定是否使用索引,尽管索引不是万能的,但数据量大的时候不使用索引是不可想象的,毕竟索引的本质,是帮助我们提升数据检索的效率。