首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

数据库索引太难,掌握下面这些就够了

索引,被称之为数据库的目录,可以让我们快速地找到对应的数据。但是,索引其实是一把双刃剑,如果使用不合理,不仅查询数据的速度不会变快,反而适得其反,让查询变慢。

工作原理

索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。使用索引,我们的目的就是要更快地查询数据。可以说,索引的本质就是空间换时间。那么,索引是如何工作的呢?

我们以上图为例,在数据库中存着两个字段,一个是主键ID,另外一个是字段K。当我们直接查询主键的时候,可以在左边的主键索引中直接找到对应的数据块,然后从磁盘中将他们读取出来,而当我们使用K字段进行查询的时候,则先要从右边的二级索引中,先找到对应的K有那些符合条件的主键,然后再去主键索引中读取相关的数据块的位置,再去磁盘中读取出来。

索引必须作为频繁查询的条件

通俗易通的说,我们应该选择WHERE后面的条件,而不是SELECT后面的元素。如果这个条件从来不做查询条件,记录了也没有什么意义。

举个简单的例子,你在开发一款快递查询系统。你想知道昨天从深圳发出的快递有多少份,那么你就应该建立一个发出时间,发出地址的快递。假如你一个索引都没建,那会发生什么事情,需要扫描所有的快递记录,逐个进行比较,才能够找到发出地点是深圳,发出时间是昨天的订单。假如你只建了发出时间是昨天的索引,那么就会扫描昨天的订单,然后逐个比较是否发出点是深圳,然后选择对应的结果。同理,如果你只建了发出地点的索引,那数据库就会帮你找到所有的深圳的订单,然后找到发出时间是昨天的。所以,最好的办法,是建立时间跟发出地点的联合索引。

一般来说,索引使用的都是最左前缀原则。这与我们索引的存储格式息息相关,我们的索引,一般都使用的是多叉排序树。举个例子,如果我们有4个字段都可能作为查询条件,假如我们建立的联合索引为(1,2,3,4),那么当我们的查询条件为(1)(1,2)(1,2,3)都是可以命中索引的。假如我们的查询条件是(1,2,4)那么也可以命中索引,不过只会使用(1,2),4需要回表读数据后才能得到结果。假如我们的查询字段是(2,3,4),那么很抱歉,我们没办法使用到这个索引。

索引最好具有唯一性

索引的数据列,当然是越特殊越好,最好是能够让数据库的查询下降几个量级的。我们举个例子,假如我们开发的是一款全国大学生统一管理软件。假如数据库中有2千万大学生。现在我们想查询籍贯为湖北的男大学生,我们该如何使用索引呢?

假如我们使用性别作为数据库索引,由于性别只有男女,所以即使命中了性别索引,扫描的数据量也是千万级别的。所以,我们应该使用更特殊的字段籍贯去作为索引,可以减少更多的数据扫描量。

但是凡是无绝对,并不是说唯一性不高的的数据我们就不建立索引。在前面我们已经讲到索引的工作流程,先在索引上找到对应的主键,然后再回表查询数据。还是上述的例子,假如我们的请求总是查询某个城市某个省份的男生/女生数量,那么,我们最好的办法是建立一个城市/性别的联合索引,这样子我们可以在索引上就能计算出最终的数据量,进而不用回表查询,提升查询的效率。这种方法,我们称之为索引覆盖,就是让查询的条件,查询的内容尽量在索引上,从而减少回表,提升效率。

索引数据不能频繁变更

在B+树索引中,索引其实是一颗多叉排序树,所以,每当索引数据变更的时候,就会调整数据。调整数据是需要代价的,假如被索引数据频繁变更的时候,将会大大影响插入的性能。举个例子,在电商系统中,我们常常有这样的场景,展示有货的商品。那么,我们可否以剩余库存的数量作为索引呢?最好不要,因为库存的变更是非常频繁的,如果使用库存数量作为索引,每次都要进行索引的调整,而库存系统的写入本来就是瓶颈之一,无疑是雪上加霜。

最后

还有很多需要注意或者优化项没办法一一说出来,大家可以多交流,多积累经验。欢迎大家关注我,共同学习,共同进步。大家的支持是我继续唠嗑的动力。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200325A0T9PL00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券