具有重复值的列上的数据库索引

Posted

技术标签:

【中文标题】具有重复值的列上的数据库索引【英文标题】:Database index on a column with duplicate values 【发布时间】:2015-03-31 02:52:55 【问题描述】:

如果有一个包含员工详细信息的表,其中包含一个 Gender 列,其值可以是 M/F。现在在此列上创建索引是否有意义,它会使搜索更快吗?从逻辑上讲,如果我们使用 where 子句包含 Gender 作为列的 select 语句,它应该将搜索时间减少一半。但是我听说这种索引没有帮助,并且在执行查询时实际上会被数据库优化器忽略。但我不明白为什么?有人可以解释一下吗?

【问题讨论】:

其实这个问题很笼统,但是尤其是Sybase 我在网上搜索但没有得到明确的答案,请给我投反对票的人解释一下,你为什么给我投反对票。可能对你来说这么简单,你能把答案也写出来吗 索引只是一个电话簿,如果名字不同,它有助于减少查找某人号码的时间,如果其中一半的名字是约翰,那么你需要搜索一半的房子。我没有给你投反对票。social.msdn.microsoft.com/forums/sqlserver/en-US/… 那么你确定如果我创建索引,它会减少一半的搜索吗?实际上它并不那么简单,因为它取决于数据库如何存储索引以及查询优化器如何工作,我听说它可能没有帮助,这就是我想要深入了解的原因 这取决于很多事情:行数、comp 上的内存、基数、索引类型、WHERE 中使用的列等等。对于 WHERE 中的单个列,它将返回一半我怀疑会使用索引的值。 【参考方案1】:

大概,性别有两个价值。一般来说,gender 上的索引不会有帮助。事实上,这可能是有害的。

如果您在没有索引的情况下选择性别,则查询优化器会对数据库页面进行全表扫描以满足查询。在典型的页面上,一半的条目会匹配查询,因此您会在第一次点击时开始获得结果。

在查询执行的这个阶段,索引通常用于减少正在读取的页面数量。但是,如果每一页都有“M”和“F”的记录,那么每一页仍然需要被读取。更糟糕的是,使用索引意味着您从一个随机页面读取,然后是另一个页面,然后是另一个页面,而不是仅按顺序读取值。跳转页面需要一些额外的时间。如果页面不能全部放入内存,就会出现一种称为抖动的情况,这可能需要非常非常长的时间。

一个例外是聚集索引,其中页面上的值实际上是按值排序的。在这种情况下,使用索引的查询会快 50% 左右,因为只需要读取页面。这在“存档”表中特别有效,在该表中,您有经常搜索的活动记录。此标志可能出现在 10%、1% 或 0.1% 的记录上,并且聚集索引可以显着提高速度。

在大表上运行返回一半记录的查询是很少见的。很可能,将性别与其他列结合起来将是包含在索引中的良好候选者。

【讨论】:

【参考方案2】:

在大多数情况下,只能使用一个索引来优化数据库查询。如果一个查询需要匹配多个索引列,查询规划器将不得不决定使用这些索引中的哪一个。每个索引都有一个基数,它大致是整个表中不同值的数量。具有较高基数的索引会更有效,因为选择与索引匹配的行将导致扫描以匹配其他条件的行数非常少。

gender 列上的索引只会将表切成两半。任何其他索引都会更有效。

作为一个类比,想想电话簿。如果您有一个完整国家/地区的电话簿,那么搜索您想要的特定人员将非常庞大且困难。所以电话簿通常只为一个城市或一个地区的几个城市制作,以使其大小合理。但如果你有一个“男性电话簿”而不是区域电话簿,它几乎就像整个国家的电话簿一样无法使用。创建新电话簿的标准是它们应该比整个国家的电话簿小得多。当您从一个巨大的尺寸开始时,减少 2 倍并不是很有用。

【讨论】:

好吧,假设我的查询需要 1 小时来执行,如果我能在半小时内完成它,对我来说仍然是一个很大的节省...... 您多久执行一次该查询?请记住,维护索引存在内存和时间开销。因此,许多其他操作会变慢,这可能会使您在那些只需要性别索引的偶尔查询上节省半个小时以上。 查询频率不高,一天可能只有几次 这就是我的观点。如果很少使用它,是否值得更新索引的所有开销? 从业务角度来看,由于某些 SLA 相关原因,我们需要快速完成查询,您正确指出的其他操作(如插入和更新)可能会有所延迟,但如果影响,这是可以接受的是合理的......

以上是关于具有重复值的列上的数据库索引的主要内容,如果未能解决你的问题,请参考以下文章

在已经存在主键或唯一键约束的列上创建索引

Mysql设计索引的原则

mysql重复索引冗余索引未使用索引的定义和查找

Oracle11G_索引

MySQL学习(十五)

MySQL数据库索引总结