MySQL-为什么不索引每个字段?


107

最近,我了解了索引的奇妙之处,并且性能得到了极大的提高。但是,据我所知,我似乎找不到该问题的答案。

索引很棒,但是为什么有人不能只索引所有字段以使表变得如此快呢?我确定有充分的理由不这样做,但是三十字段表中的三个字段又如何呢?30个字段中有10个?一个人应该划界线,为什么呢?


7
尝试将一个值插入具有索引的超过10k条目的表中,由于插入/删除操作,所有条目都必须更新,如果每个值都有一个索引,这将占用大量时间,并且有些内存开销
Jesus Ramos

5
除了空间和写入性能外,还有一个原因:对单个表访问使用多个索引效率很低。这意味着,即使在每一列上都有一个索引,如果在WHERE子句中访问了多列,选择性能也不是很好。在这种情况下,最好使用多列索引。
Markus Winand

1
如果您有一个包含30个字段的表,则应真正查看表结构。他们应该非常努力地工作。
腹板

Answers:


122

索引占用内存(RAM)中的空间;索引太多或太大,数据库将不得不在磁盘之间来回交换它们。它们还会增加插入和删除时间(必须为每个插入/删除/更新的数据更新每个索引)。

您没有无限的记忆。使所有索引都适合RAM =好。

您没有无限的时间。仅对需要索引的列建立索引可最大程度地减少插入/删除/更新性能的影响。


11
这是一个不错的随意答案,可以使您大致理解,但在实际确定索引的位置时并没有太大帮助。你怎么知道 只需将它们添加到常用的WHERED字段中,并希望获得最好的?
安德鲁

@安德鲁一年半之后,您找到问题的答案了吗?
Sinjai

1
@Sinjai将它们通常添加到列中可能是一个很好的经验法则。但是,如果您想成为索引方面的专家,那么您可能会做大量的阅读工作。例如。stackoverflow.com/questions/3049283/…–
安德鲁(Andrew)

不要忘记磁盘空间。
jpmc26

27

请记住,每当更新,插入或删除行时,都必须更新每个索引。因此,拥有的索引越多,写入操作的性能就会越慢。

同样,每个索引占用更多的磁盘空间和内存空间(在调用时),因此它也可能会减慢读取操作(对于大型表)。 看一下这个


6
该链接是针对MS SQL Server的;这个问题是MySQL的
OMG小马

5
@OMG链接中的大部分内容适用于所有主要的RDBMS
RichardTheKiwi 2011年

5
@Richard aka cyberkiwi:ANSI并未涵盖索引-每个供应商都使用类似的术语是一个奇迹。但是即使那样,只有SQL Server和MySQL都使用术语“聚集”和“非聚集”索引-在SQL Server中,这比MySQL意味着更多。没有任何保证可以将针对一个供应商的建议应用于另一供应商。
OMG Ponies,

3
@omg前6点适用于所有dbms。跳过非/聚集索引,然后在下面列出与常规索引有关的更多要点,也包括要点。如果您有特定的要指出的地方,请给他们打电话。否则,看起来您正在否定评论中的所有答案(包括已删除的答案),没有人同意您的评估。
RichardTheKiwi 2011年

10

您必须平衡CRUD的需求。写入表变慢。至于在哪里画线,这取决于如何访问数据(排序过滤等)。


并且每个索引都占用一些数据库空间
Acanthus

@Acanthus:可用的最小硬盘驱动器以GB为单位
OMG Ponies,

4
@OMG但不是RAM,正如Brian指出的那样。存储超过所需数量绝不是一个好主意。RAM中的数据/索引缓存,备份媒体(适用于每个磁带的版本等)均受无用索引影响
RichardTheKiwi 2011年

9
资源丰富并不是浪费或效率低下的原因。
Smandoli 2011年

6
的确如此,但这些限制与10年前的限制不同。
OMG Ponies,

2

索引将占用更多的驱动器和内存分配空间,但也会大大提高性能。不幸的是,当达到内存限制时,系统将占用驱动器空间并降低性能。实际上,您不应该索引任何您认为不涉及任何类型的数据遍历算法的字段,也不要插入或搜索(WHERE子句)。但是,如果没有,则应该这样做。默认情况下,您必须索引所有字段。如果查询仅由主持人使用,则应考虑取消索引编制的字段,除非它们也需要提高速度


2

这个答案是基于我的个人观点,我正在使用我的数学逻辑来回答

第二个问题是关于边界的停靠点,首先进行一些数学计算,假设我们在一个表中有N行,其中L个字段,如果我们对所有字段建立索引,我们将获得L个新的索引表,其中每个表都将按有意义的是索引字段的数据,乍看之下,如果您的表是W权重,那么如果您有100个大表(我已经在项目表号为arround 1800 table),您将浪费100倍的空间(100 tera),这与明智之举相去甚远。

如果要在所有表中应用索引,我们将不得不考虑索引更新是一次更新触发所有索引更新,这是时间上所有无序选择的等效项

由此我得出的结论是,在这种情况下,如果您要放宽此时间,则最好在选择或更新中丢失它,因为如果您选择未索引的字段,则不会在所有没有索引

索引什么?

外键:必须基于

primary-key:我尚不确定这是否有人阅读此书可以解决这种情况

其他字段:第一个自然答案是剩余污点的一半为什么:如果您应该编制更多索引,您应该离最佳答案不远;如果您应编制更少索引,您也不会相距遥远,因为我们知道没有索引是不好的,并且所有索引都已编制也是不好的

从这三点可以得出结论,如果我们有由K个键组成的L个字段,则限制应该在((L-K)/2)+KL / 10左右

这个答案是基于我的逻辑和个人习惯


1

索引表中的所有列不是一个好主意。虽然这将使表的读取速度非常快,但写入速度也变慢了很多。写入对每个列都建立索引的表将涉及将新记录放入该表中,然后将每个列的信息放入其自己的索引表中。


我不确定这是否会使读取表快如闪电,特别是如果数据表仅为100MB但index.table为300MB或更多。
戴维

你说的一切都已经讲过了。
Vael Victus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.