【问题标题】:Is a many-field index on a large table a good idea?大表上的多字段索引是个好主意吗?
【发布时间】:2013-02-27 04:52:29
【问题描述】:

我以前从未设计过大型数据库,所以我从不关心索引。但是,现在我正在做一个需要大型数据库的大型项目。所以我正在确定我将在内部连接中使用它作为索引的每个表。

例如,其中一张大表具有如下字段:

Userid
Industryid
Teamid
Zoneid

我想要的任何东西都是指向第二张桌子的标识。所以我已经索引了这些。

此表有 60 个字段,但其中 16 个已编入索引 + 1 个主字段。

如果有这么大的表包含所有这些索引是个好主意吗?我预计这张表在 1 年内将超过 400 万条记录。我这样做的原因是为了让这张表与其他表之间的内部连接更容易和更快

在如此大的项目中使用索引的最佳方式是什么?

【问题讨论】:

  • 所有四个字段看起来都可能是外键。而这四个组合的可能是一个自然的主键。我无法说出其他 12 个索引,但是对于数据模型而言,包含 60 个字段和 12 个索引的表看起来有点可疑。
  • 实际上其中 12 个是外键,4 个是可搜索的。所以对于 eaxample 我有用户 ID 和用户名,尽管我有用户名是第二个表,称为使用。而且我不确定我是否在这里打对了电话,但这将在如此大的桌子上消除 1 个内部联接。此外,即使用户名因任何原因更改,它也会将用户名保留在历史记录中。
  • 拥有一个包含 16 个 FK 的表要么违反 3NF/BCNF,要么是艺术品。避免(内部)连接的非规范化听起来像是过去的坏习惯,IMnsHO。

标签: sql database-design indexing


【解决方案1】:

此表有 60 个字段,但其中 16 个已编入索引 + 1 个主字段。

这个看起来有点过分了,但是如果你真的需要所有这些索引那就没关系了。

索引不是免费的:每个额外的索引都会占用空间,并且在修改数据时需要维护1,以换取搜索数据时的加速(假设使用正确)。您可以根据自己的具体情况确定正确的权衡取舍。

如果有这么大的表包含所有这些索引是个好主意吗?

在 FK 上建立索引几乎总是一个好主意,因此 DBMS 可以以良好的性能维护 FK。具体来说,每当删除父行或更新引用的键时,DBMS 都必须搜索子行。从理论上讲,如果您从不删除/更新父级,那么您实际上也不需要 FK 上的索引,尽管某些 DBMS 无论如何都会强制您拥有它们。

这些索引可以对 JOINins 有用(并且通常是),但这实际上取决于如何您 JOIN 以及您 DBMS 的查询规划器的能力。2

在如此大的项目中使用索引的最佳方式是什么?

对于每个对性能敏感的查询,仔细检查查询执行计划并根据代表性数据量衡量实际时间。仅仅因为查询在小表上以一种方式执行,doesn't mean 它会在表增长时以同样的方式执行。

最后但同样重要的是,我强烈推荐阅读Use The Index, Luke!


1 每次向表中插入一行时,DBMS 必须在索引 B-tree 中插入相应的键。当行被删除时,键将从索引中删除。更新索引字段时,需要删除旧键并插入新键。您的表上的索引越多,每当您在该表中插入/更新/删除一行时,DBMS 就必须花费更多的时间来执行此“索引维护”。

2 JOIN 的执行方式有很多种:各种顺序的嵌套循环、合并连接、散列连接……不同的策略可能需要不同的索引甚至不同的索引的种类(例如,B 树对散列连接没有多大用处)。并非所有 DBMS 都能够使用所有这些策略,也不是在理论上可以使用现有索引的所有情况下都使用它们。因此,适用于一个 DBMS 的索引策略不一定适用于另一个 DBMS。有时,您可以保留索引,但您必须通过使用“查询提示”或使用对特定 DBMS 的查询优化器“友好”的语法,向正确的方向“轻推” DBMS,甚至尽管可能存在等效但更易于阅读的语法。例如,旧版本的 MySQL 将始终执行 IN 子查询作为嵌套循环的内部之一,即使在循环的反向顺序或合并连接会更快的情况下也是如此。这就是为什么人们经常在 MySQL 下推荐 rewriting IN as JOIN 的原因(尽管我听说他们在 MySQL 5.6 中修复了这个问题)。 OTOH,在 Oracle 下将 IN 重写为 JOIN 不是很有用,因为 Oracle 在等效执行等效查询方面要好得多,即使存在语法差异。

【讨论】:

  • 感谢您提供如此好的反馈。当你说索引不是免费的并且需要维护时,你到底是什么意思?需要什么样的维护?您的意思是“您的 DBMS 的查询规划器的能力如何。”感谢您的提示:)
  • 布兰科,非常感谢您的帮助,这让我更清楚了:)
猜你喜欢
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 2011-09-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多