20分钟数据库索引设计实战

在后端开发的工做中如何轻松、高效地设计大量数据库索引呢?经过下面这四步,20分钟后你就不再会为数据库的索引设计而发愁了。数据库

顺畅地阅读这篇文章须要了解数据库索引的组织方式,若是你还不熟悉的话,能够经过另外一篇文章来快速了解一下——数据库索引融会贯通后端

这篇文章是一系列数据库索引文章中的第三篇,这个系列包括了下面四篇文章:bash

  1. 数据库索引是什么?新华字典来帮你 —— 理解
  2. 数据库索引融会贯通 —— 深刻
  3. 20分钟数据库索引设计实战 —— 实战
  4. 数据库索引为何用B+树实现? —— 扩展

这一系列涵盖了数据库索引从理论到实践的一系列知识,一站式解决了从理解到融会贯通的全过程,相信每一篇文章均可以给你带来更深刻的体验。post

1. 整理查询条件

咱们设计索引的目的主要是为了加快查询,因此,设计索引的第一步是整理须要用到的查询条件,也就是咱们会在where子句、join链接条件中使用的字段。通常来讲会整理程序中除了insert语句以外的全部SQL语句,按不一样的表分别整理出每张表上的查询条件。也能够根据对业务的理解添加一些暂时尚未使用到的查询条件。优化

对索引的设计通常会逐表进行,因此按数据表收集查询条件能够方便后面步骤的执行。网站

2. 分析字段的可选择性

整理出全部查询条件以后,咱们须要分析出每一个字段的可选择性,那么什么是可选择性呢?spa

字段的可选择性指的就是字段的值的区分度,例如一张表中保存了用户的手机号、性别、姓名、年龄这几个字段,且一个手机号只能注册一个用户。在这种状况下,像手机号这种惟一的字段就是可选择性最高的一种状况;而年龄虽然有几十种可能,可是区分度就没有手机号那么大了;性别这样的字段则只有几种可能,因此可选择性最差。因此俺可选择性从高到低排列就是:手机号 > 年龄 > 性别。设计

可是不一样字段的值分布是不一样的,有一些值的数量是大体均匀的,例如性别为男和女的值数量可能就差异不大,可是像年龄超过100岁这样的记录就很是少了。因此对于年龄这个字段,20-30这样的值就是可选择性很小的,由于每个年龄都有很是多的记录;可是像100这样的值,那它的可选择性就很是高了。code

若是咱们在表中添加了一个字段表示用户是不是管理员,那么在查询网站的管理员信息列表时,这个字段的可选择性就很是高。可是若是咱们要查询的是非管理员信息列表时,这个字段的可选择性就很是低了。索引

从经验上来讲,咱们会把可选择性高的字段放到前面,可选择性低的字段放在后面,若是可选择性很是低,通常不会把这样的字段放到索引里。

3. 合并查询条件

虽然索引能够加快查询的效率,可是索引越多就会致使插入和更新数据的成本变高,由于索引是分开存储的,全部数据的插入和更新操做都要对相关的索引进行修改。因此设计索引时还须要控制索引的数量,不能盲目地增长索引。

通常咱们会根据最左匹配原则来合并查询条件,尽量让不一样的查询条件使用同一个索引。例若有两个查询条件where a = 1 and b = 1where b = 1,那么咱们就能够建立一个索引idx_eg(b, a)来同时服务两个查询条件。

同时,由于范围条件会终止使用索引中后续的字段,因此对于使用范围条件查询的字段咱们也会尽量放在索引的后面。

4. 考虑是否须要使用全覆盖索引

最后,咱们会考虑是否须要使用全覆盖索引,由于全覆盖索引没有回表的开销,效率会更高。因此通常咱们会在回表成本特别高的状况下考虑是否使用全覆盖索引,例如根据索引字段筛选后的结果须要返回其余字段或者使用其余字段作进一步筛选的状况。

例如,咱们有一张用户表,其中有年龄、姓名、手机号三个字段。咱们须要查询在指定年龄的全部用户的姓名,已有索引idx_age_name(年龄, 姓名),目前咱们使用下面这样的查询语句进行查询:

SELECT *
FROM 用户表
WHERE 年龄 = ?;
复制代码

通常状况下,将一个索引优化为全覆盖索引有两种方式:

  1. 增长索引中的字段,让索引字段覆盖SQL语句中使用的全部字段
    • 在这个例子中,咱们能够建立一个同时包含全部字段的索引idx_all(年龄, 姓名, 手机号),以此提升查询的效率。
  2. 减小SQL语句中使用的字段,使SQL须要的字段都包含在现有索引中
    • 在这个例子中,其实更好的方法是将SELECT子句修改成SELECT 姓名,由于咱们的需求只是查询用户的姓名,并不须要手机号字段,去掉SELECT子句多余的字段不只可以知足咱们的需求,并且也不用对索引作修改。