一、什么是数据库索引
数据库索引,类似于图书馆中的分类查询卡片,用于快速的对数据库进行查询。索引原理,简单来说,就是针对数据库中某个字段的数据,进行排序,存储在另一个专门的索引数据表中。然后在针对该字段的查询时,使用二分法快速从索引数据表中定位到相应记录的数据ID,再根据这个数据ID,从原始表中返回需要查询的记录信息。
举个例子,我们把数据库里的数据,想象成是一个图书馆里的所有的书,假设,我们现在有这些书:
注意,这些书的排列顺序,是按入库时间来的,这个也是通常数据的排列顺序,即先来的排在前面,后来的排在后面。在数据库里,数据的默认顺序,也是按时间从前向后排。
接下来,假设有一个同学来找我们要“澳洲龙虾养殖大法”这本书,在没有其他信息的情况下,要在整个图书馆里找一本书,只能是一本一本的去找。如果恰好这本书排在后面,那就要找遍整个图书馆。为了要让我们找书的速度加快,我们可以建立一个索引表,比如,按书名的首字母拼音进行排序:
这个时候,我们要找“澳洲龙虾养殖大法”,就可以像字典一样在这个书名索引表里很快的找到它的位置,并直接去相应的位置拿到书,而不需要一本一本的去找了。
有时候,用户可能除了要找某本具体书名的书,还可能要按其他的方法来查找。比如,按作者。假设,某个同学想要借走所有“张三”这个作者的书。那这个时候,上面按书名的索引表就不能满足需求了,要所有“张三”的书,还是要去图书馆里一本一本的找,即“遍历”。因此,我们可以再建立一张作者索引表:
按作者分类排序的索引表,这样我们就可以很快找到张三这个作者所有的书了。
在以上的例子中,我们的书的总量,或者数据的总量,只有6条,因此感受可能不太明显。但在实际的数据库应用中,表的数据可能超过百万条,那这个时候,按索引表去找数据,和从头到尾遍历数据的速度对比,就相当明显了。
在实际的数据库中,索引的实现有各种不同的方法,也有很复杂的技术细节,但基本的原理就和我们以上图书馆的例子是一样的。大家有兴趣可以深入了解一下各种索引的具体实现。
二、什么时候需要添加索引
上一节中,我们已经了解到了索引的作用是帮助我们快速定位到数据库里的某条数据。那具体在什么场景下,我们需要“快速定位数据”呢?在我们的日常数据库操作中,其实主要有两个地方:
一是数据筛选时,包括筛选输出,筛选统计,筛选更新等等,比如,我们在输出数据时填的字段:
在以上输出中,我们要输出所有姓名=“张三”的记录,因此,数据库为了要给我们找到所有姓名为张三的记录,就要和图书管理员一样,去整个库里一条一条的找,看看每一条记录的“姓名”字段,是不是“张三”,如果是,就返回给我们。因此,在这种情况下,如果我们的数据比较多时,就建议添加索引了。添加索引后,数据库系统会自动创建一个索引表,把所有“姓名”这个字段的值都按某种方式进行排列,这样就可以像拼音索引一样,很快的找到所有张三的记录,返回给我们了。
无论是输出还是更新还是统计,只要涉及到筛选,都要求数据库先定位到这些符合条件的记录,因此当数据量多的时候,都需要添加索引。
二是数据排序时,排序在我们看来是一个很简单的活,但对于大数据量的表来说,排序是一个大工程。无论是用何种方法排序,都需要用到快速定位数据的方法。因此,在数据量大时,我们也需要为排序的字段添加上索引。
最后,我们在文中一直提到“数据量大时”要加索引,那怎样才算数据量大呢? 其实这个问题并没有标准答案,是一个模糊的范围,首先,几百条数据,肯定不属于数据量大,超过1w,就属于数据量大了。那几千条数据,算不算“数据量大”,凭个人的经验,通常超过5000条数据,可以考虑加索引,小于5000,就不用了。但4999条,是不是加索引,这个就看我们具体的应用场景了,因为索引,也是有成本的。我们在下一节中来详细讲。
三、什么时候不需要添加索引
上文中,我们充分了解了“索引大法”的优势,那为什么ivx系统不默认给所有字段都加上索引,还要我们费神去选呢?因为“天下没有免费的午餐”,索引也是有成本的,其成本主要包括:
1、增加了存储空间,因为索引表需要占用额外的存储空间;
2、创建索引表时,需要一定的时间,且此时数据库会被锁定,无法操作。因此,建议我们在数据库创建时,就为需要的字段创建索引,而不是在数据库已经有一定数据量时再去创建索引;
3、由于需要维护索引表,因此创建索引会导致数据库的插入、更新与删除操作消耗更多的时间。
因此,索引并不是越多越好,我们需要按需添加索引,即针对大量数据高频查询的字段去添加索引。否则,乱加索引,可能会导致我们的数据维护成本以及数据插入的服务成本过高。假设一个字段,既没有在筛选的时候用到,又没有在排序的时候用到,只是作为普通的数据进行输出,那就不需要加索引了,因为加了索引也是浪费。比如,我们有一个“人员描述”字段,是个特别长的文本描述,我们并不需要按“人员描述”去数据库里搜索数据,它只是一个“附加信息”字段,这类字段,就没有必要加索引了。
总结一下,以下情况肯定不用加索引:
数据量少,比如,小于1000条时;
没有在筛选或排序中用到的字段;
查询频率非常低的字段
四、iVX中数据库的索引
在iVX中的数据库,我们可以在数据库右侧的索引面板中为字段添加索引。任何一个新建的数据库,系统会自动添加3个索引:即数据ID主键索引,提交用户与创建时间:
其中,数据ID作为主键索引,无法删除。其他两个默认添加的所以,如果我们不需要查询,可以删除,以提高数据插入的速度。
如果我们要额外添加所以,可以点击“添加索引字段”,选择需要添加所以的字段即可。
添加索引之后,我们可以看到左边还有一个“数据唯一”的开关:
打开这个开关后,这个字段索引就会升级为“独立唯一索引”,即它就不能插入重复的数据了。如果当前字段已经存在重复数据,则这个开关打开时会弹窗提示报错。独立唯一索引,除了可以限制数据不可重复外,还能够提高数据查询效率。
五、联合索引
除了添加单个索引,我们还可以添加联合索引。只要点击索引右边的“+”号即可:
所谓联合索引,即为两个或多个字段的值同时建立索引,其主要作用是加快多个条件查询的速度(这里的多个条件仅指“且”条件)。举个例子,我们经常要查询“类型”=xx且“地区”=xx的某个商品,此时,我们可以为“类型”字段与“地区”字段添加联合索引,这样,系统会自动把数据库里每条数据的类型与地区的值一起记录并索引,这样,查询“类型”=xx且“地区”=xx的商品时,数据库可以很快定位到相应的记录。
六、联合索引 VS 单个索引
当我们为N个字段添加联合索引时,比如 a、b、c这三个字段添加了联合索引,系统在内部会建立a字段索引,a+b字段的联合索引,以及a+b+c字段的联合索引。因此,我们可以看到,联合索引的消耗也是比较高的。那什么时候添加联合索引呢?我们主要总结了两种场景:
两个或多个字段经常作为查询组合,且这几个字段联合之后的值的多样性明显大于单个。举个例子,假设我们要查询"提交用户"=xxx且“订单号”=xxx的记录,但订单号是一个多样性很高的字段,比如,通常一个用户只有一个订单号,偶尔一个用户有两个。或者换个说法,我们数据库里有1w条数据,而订单号就有9k个。那这个时候,为订单号和提交用户添加联合索引的意义就不大,因为订单号一个字段的多样性就有9k,添加了联合索引之后,多样性只是从9k增加到了1w。考虑到联合索引的成本,此时就没有必要添加。但如果一个用户通常有超过10个订单号,那这个时候添加用户X订单号的联合索引,就可以大大提高索引的多样性。
多个字段的独立唯一性,这是一个非常“可爱”的功能。我们经常会有这种需求,比如,一个用户只能为一个候选人投一票,或者一个用户只能为另一个用户助力一次,一个用户每天只能领一次红包。在没有联合索引之前,我们只能去数据库里查找,用户A是否为候选人1投过票,如果有,就可以投,否则不可以投。此时,如果我们恰好没有做事务,在高并发的时候,还会产生数据不一致的问题。但现在,我们可以用联合的独立唯一索引来解决问题,只需要给用户与候选人添加联合索引,并将这个联合索引设置为数据唯一:
就可以在提交时自动限制每个用户只能为每个候选人投一票了。这种做法除了节省后台运算资源之外,还从底层保证了数据的一致性。所以非常建议大家用这种方法来限制用户的投票、领红包、领奖等行为。(当然,它也不是万能的,独立唯一索引,只能限制一条记录,不能限制一个用户仅能为另一个候选人投2票,如果碰到超过1票的情况,建议还是自己用事务来实现)
关于联合索引和单个索引的使用场景,网上还有很多其他的文章,我们这里只是总结了两种最常见的联合索引场景。大家可以多在网上找找经验文章,欢迎在评论区分享~
共同学习,写下你的评论
评论加载中...
作者其他优质文章