数据库索引遵循的最佳实践


17

有哪些DO和DONT使用索引来提高数据库性能?

DO应该是应该创建索引的情况,或者是与索引相关的,可以提高性能的技巧。

如果不应该创建索引,或者其他可能影响性能的索引相关操作,则不要使用DONT。


3
个人资料,个人资料,个人资料
GrandmasterB

Answers:


15

这部分取决于数据库的用途,因为通常索引会减慢插入和更新的速度并加快查询的速度。在数据仓库中,通常没有更新和批处理插入,这使得创建索引和进行大量查询的索引变得更加容易,而查询却被大量索引加速了。在用于网络销售等的在线数据库中,有大量的插入和更新,因此拥有多个精心选择的索引只会降低它的速度。

如果您收到许多特定类型的查询,则可以为查询创建一个索引,尽管在线索引处理比数据仓库更多。如果某些列在查询中出现很多,您可能希望在该列上建立索引,这对于数据仓库尤其有用,因为数据仓库以许多不同且通常是不可预测的方式被查询。

每当您添加或删除索引时,请尝试进行性能测试以查看其效果。没有这些,您就会失明。

关于调优查询和数据库的书籍,通常是特定于一个数据库系统并使用该RDBMS工具的。但是,如果您发现自己需要大量优化数据库,那么您正在进行大量的操作,可能应该雇用具有适当专业知识的DBA。


17

这在很大程度上取决于您如何使用表格。没有一个简单的答案。

我能给您的最佳建议是:使用调音顾问。他们将在您使用该应用程序时分析数据库命令,然后将对其执行负载测试以为您提供有意义的建议。

它们存在于SQL ServerOracle中。我不知道其他DBMS是否拥有它们,只是我怀疑它们没有提供这样的基本工具。

很少有随机的建议:

  • 将索引应用于经常包含在WHERE子句中的列时,可以提高性能
  • 将聚集索引用于查询中最常用的列。
  • 别忘了您可以使用列组合创建多个索引(因为它们在查询中使用)
  • 索引过多会降低INSERT命令的性能。

最后建议:如果数据库性能对您的项目确实很重要,请聘请专家。是我做的


2
+1为列组合索引。在列的索引a并且b一样的索引(a, b)。后者是几乎一样好该指数a用于对符合条件加快查询a,是大规模更好地与条件的查询上ab,和是不是在查询有用的b孤独。(大多数数据库不会使用它。Oracle会使用它,但不会像
往常

2
+1,将添加“学习阅读查询计划,以便您知道要编制索引”
Steven A. Lowe

4

@Pierre 303已经说过了,但我会再说一遍。 不要在列的组合上使用索引。(a, b)对于查询而言,组合索引打开仅a比对a单独索引而言稍慢,并且如果您的查询将两个列都合并,则合并索引会更好。有些数据库可以在命中表之前ab之后连接索引,但这远不及合并索引。创建组合索引时,应将最有可能被搜索的列放在组合索引中。

如果你的数据库支持的话,DO穿上,在查询,而不是列显示的功能指标。(如果要在列上调用函数,则该列上的索引是无用的。)

如果您使用的是数据库与真正的临时表,你可以创建和销毁的飞行(如PostgreSQL的,MySQL的,但不是甲骨文),则不要创建临时表的索引。

如果您使用的数据库支持的话(如Oracle),DO锁定良好的查询计划。随着时间的推移,查询优化器将更改查询计划。他们通常会改善计划。但是有时它们会使情况变得更糟。您通常不会真正注意到计划的改进-查询不是瓶颈。但是,一个糟糕的计划可能会使繁忙的站点瘫痪。

不要对你想说的话在大数据负载表的索引。与在加载表时维护索引相比,删除索引,加载数据然后重建索引要快得多。

不要在必须访问大型表中很小一部分的查询上使用索引。(大小取决于硬件。5%是一个不错的经验法则。)例如,如果您的数据包含名称和性别,则名称是索引的不错选择,因为任何给定名称都占总行的一小部分。索引性别并没有帮助,因为您仍然必须访问50%的行。您确实想使用全表扫描。原因是索引结束随机访问大文件,导致您需要磁盘搜索。磁盘搜寻很慢。作为一个例子,我最近设法加快了一个小时的查询,如下所示:

SELECT small_table.id, SUM(big_table.some_value)
FROM small_table
  JOIN big_table
    ON big_table.small_table_id = small_table.id
GROUP BY small_table.id

通过以下方式重写到3分钟以内:

SELECT small_table.id, big_table_summary.summed_value
FROM small_table
  JOIN (
      SELECT small_table_id, SUM(some_value) as summed_value
      FROM big_table
      GROUP BY small_table_id
    ) big_table_summary
    ON big_table_summary.small_table_id =  small_table.id

这迫使数据库了解到,不应尝试在上使用诱人的索引big_table.small_table_id。(一个好的数据库,例如Oracle,应该自行解决。此查询在MySQL上运行。)

更新:这是我所做的磁盘搜索点的说明。索引使您可以快速查找数据在表中的位置。通常这是一个胜利,因为您将只查看需要查看的数据。但并非总是如此,特别是如果您最终将要查看大量数据时。磁盘可以很好地传输数据,但是会使查询变慢。随机查找磁盘上的数据需要1/200秒。慢速查询的版本完成了大约600,000次,耗时近一个小时。(它进行的查找更多,但是缓存捕获了其中的一些。)相比之下,快速版本知道它必须读取所有内容并以70 MB /秒的速度传输数据。它在3分钟内通过了11 GB的表。


嗨,我为您的例子感到困惑。我本以为使用索引可以使事情变得更快,这不是索引的重点吗?您是说如果查询将访问表的5%以上,然后在要搜索的列上建立索引会使速度变慢?
点击Upvote 2011年

@Click Upvote:如果查询访问表的5%(确切程度取决于硬件和数据),则不使用该查询的索引会更快。只要不使用索引,索引就不会受到伤害。我将更详细地说明原因。
btilly 2011年

有用的信息。关于此的更多信息,例如mysqlperformanceblog.com/2007/08/28/…但是我想知道,“忽略键”是否不符合您需要使其成为子查询的条件?
印加

@Inca:我不知道“忽略键”。我切换数据库的程度足以使我经常不了解某些特定于数据库的内容。从听起来似乎可行,但效率远低于我最终的解决方案。所不同的是,将加入,然后分组,而我的分组,然后加入。这样可以节省连接工作,因为需要连接的记录较少。
btilly 2011年

“一个很好的数据库(例如Oracle,但不是MySQL)”:请避免这样的愚蠢的促销活动,尤其是当您忽略MySQL可以完美同时使用多个索引的事实时(在查询计划中标记为“ INDEX MERGE”) 。
帕特里克·阿拉特

2

应做的事情:为通过查询和/或比较访问最多的很少几个字段编制索引。

请勿:将表中的每个字段编入索引,以为这样做会更快。

我没有任何统计信息,但是如果可以的话,我尝试在一个表中保留不超过4个索引字段。归一化我的数据库通常有助于使这些数字保持不变,因为所有内容都可以通过数字键进行搜索(无论如何都更快)。我尝试远离全文本字段进行索引。他们很重。


2

基本上,索引可加快搜索速度,但会减慢写入速度,并且会占用空间。那就是要做出的权衡。

经常用于连接,搜索/比较或排序的任何字段都是索引的候选项。要知道它确实是有益的,要衡量一下。但是,具有大量记录(> 1000s)和很少插入的紧密连接表的外键将得到回报。

对于文本字段,您可以在字段的一部分上建立索引(例如,前6个字符),这将加快查询速度,但减轻索引的负担。全文搜索(在上搜索like %substring%)需要使用不同的技术,而我不熟悉这些技术,因此在此我不能给您提供建议。

索引无济于事的重要情况:在部分日期上搜索(/联接/顺序)时,无法使用完整日期或日期时间字段的索引。上的索引date_created不会帮助您进行类似的查询select * from t where year(date_created) = 2011。在mysql中,您无法在部分日期上创建索引。(当您使用' between而不是year()它时,可以在日期字段上使用索引。)

手册中有关MYSQL的更多信息:http : //dev.mysql.com/doc/refman/5.6/en/optimization-indexes.html


1

请执行以下操作:尽量使聚集索引的总大小最小。聚簇索引条目将包含在其他非聚簇索引中,因此有可能浪费磁盘空间。


1

可以将表视为词典,按照外观顺序(或根本没有帮助顺序)对文章进行排序,将表索引视为该词典的书籍索引。

您可以使用索引来快速查找书中的内容。您无需扫描整本书,只需查找索引中的键(索引通常以某种方式排序(按类别,按科学领域,按历史时期等等),这也意味着您不必扫描整个索引),然后跳到正确的页面。

但是,与书籍不同的是,一张桌子不会被一次印刷然后不可改变。它一直在更新,因此每个索引都必须随之更新。当然,这是在时间和空间上付出代价的,只有通过索引的有用性才能证明这一点。

因此,如果该列在频繁的搜索查询中用作键,请为该列使用索引,否则请不要使用索引。一般而言,“ 频繁 ”一词是一个很好的量词。最后,您必须对哪些是经常使用的做出一个很好的估计,然后在有疑问的情况下简单地对有或没有索引的性能进行基准测试。

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.