我之前从未设计过大型数据库,所以我从不关心索引。但是,现在我正在开发一个需要大型数据库的大型项目。所以我正在识别我将在内连接上使用它作为索引的每个表。
就像一个例子中的一个大表有这样的字段:
Userid
Industryid
Teamid
Zoneid
我的任何东西都是指向第二张桌子的身份证明。所以我已将这些索引编入索引。
此表有60个字段,但其中16个是索引+ 1个主字段。
如果有一个包含所有这些索引的大型表,这是一个好主意吗?我期待这个表在一年内有超过400万条记录。我之所以这么做的原因是为了让这个表与其他表之间的内连接变得更容易和更快
在这么大的项目中使用索引的最佳方法是什么?
答案 0 :(得分:1)
此表有60个字段,但其中16个已编入索引+ 1个主要字段。
这个看起来有点过分,但如果你真的需要所有这些索引,那就没关系了。
索引不是免费的:每个附加索引都占用空间,并且在修改数据时需要维护 1 ,以便在搜索数据时返回加速(假设它已正确使用)。您可以根据具体情况确定正确的权衡。
如果有一个包含所有这些索引的大型表是个好主意吗?
在FK上拥有索引几乎总是一个好主意,因此DBMS可以保持FK具有良好的性能。具体来说,每当删除父行或更新引用的键时,DBMS都必须搜索子行。从理论上讲,如果你从不删除/更新父级,你也不会真正需要FK上的索引,尽管有些DBMS会强迫你在任何情况下使用它们。
这些索引 可以(通常是)对JOINins有用,但这实际上取决于你加入的 以及DBMS的查询规划器的能力。< SUP> 2
在这么大的项目中使用索引的最佳方法是什么?
对于每个对性能敏感的查询,请仔细检查查询执行计划并测量代表性数据量的实际时间。仅仅因为查询在小表上以一种方式执行,doesn't mean它将在表增长时以相同的方式执行。
最后但并非最不重要的是,我热烈建议您阅读Use The Index, Luke!
1 每次在表中插入一行时,DBMS都必须在索引B-tree中插入相应的键。删除该行后,将从索引中删除该键。更新索引字段时,需要删除旧密钥并插入新密钥。您在表上拥有的索引越多,每当您在该表中INSERT / UPDATE / DELETE行时,DBMS必须花费更多的时间来执行此“索引维护”。
2 有很多方法可以执行JOIN:各种顺序的嵌套循环,合并连接,散列连接......不同的策略可能需要不同的索引甚至不同的种类的索引(例如,B树对散列连接没有太大帮助)。并非所有DBMS都能够在理论上使用它们时能够使用所有这些策略,也不能在所有情况下使用现有索引。因此,适用于一个DBMS的索引策略可能不一定适用于另一个DBMS。有时,您可以保留索引,但是您必须通过使用“查询提示”或使用对特定DBMS的查询优化器“友好”的语法,向正确的方向“轻推”DBMS,甚至虽然可能存在等效但更易读的语法。例如,旧版本的MySQL总是会执行IN子查询作为嵌套循环的内部查询,即使在循环的反向顺序或合并连接会更快的情况下也是如此。这就是人们经常在MySQL下推荐rewriting IN as JOIN的原因(尽管我听说他们在MySQL 5.6中修复了这个问题)。 OTOH,在Oracle下重写IN作为JOIN并不是很有用,因为Oracle在等效执行等效查询方面要好得多,即使存在语法差异。