120

我正在开发一个具有相当大的 Oracle 数据库的项目(尽管我的问题同样适用于其他数据库)。我们有一个网络界面,允许用户搜索几乎任何可能的字段组合。

为了使这些搜索快速进行,我们正在为我们认为用户通常会搜索的字段和字段组合添加索引。但是,由于我们并不真正知道我们的客户将如何使用该软件,因此很难判断要创建哪些索引。

空间不是问题;我们有一个 4 TB 的 RAID 驱动器,我们只使用了其中的一小部分。但是,我担心索引过多可能会导致性能下降。因为每次添加、删除或修改行时都需要更新这些索引,所以我想在一个表上拥有数十个索引是个坏主意。

那么有多少索引被认为是太多了?10?25?50?还是我应该只涵盖真正、非常常见和明显的案例而忽略其他所有内容?

4

17 回答 17

96

这取决于表上发生的操作。

如果有很多 SELECT 并且更改很少,请索引所有你喜欢的......这些将(可能)加快 SELECT 语句的速度。

如果表受到 UPDATEs、INSERTs + DELETEs 的严重影响......这些会非常慢,因为有很多索引,因为每次发生这些操作之一时都需要修改它们

话虽如此,您可以清楚地向一个不会做任何事情的表添加许多无意义的索引。将 B-Tree 索引添加到具有 2 个不同值的列将毫无意义,因为它不会在查找数据方面添加任何内容。列中的值越独特,它就越能从索引中受益。

于 2008-09-26T18:52:53.643 回答
47

我通常是这样进行的。

  1. 获取典型一天对数据运行的真实查询的日志。
  2. 添加索引,以便最重要的查询命中其执行计划中的索引。
  3. 尽量避免索引具有大量更新或插入的字段
  4. 在几个索引之后,获取一个新的日志并重复。

与所有任何优化一样,当达到请求的性能时我会停止(这显然意味着点 0. 将获得特定的性能要求)。

于 2008-09-26T18:58:28.450 回答
26

其他人一直在给你很好的建议。在你前进的过程中,我有一个额外的建议给你。在某些时候,您必须决定您的最佳索引策略。但最终,最好的 PLANNED 索引策略最终仍然会创建最终不会被使用的索引。让您找到未使用的索引的一种策略是监视索引使用情况。你这样做如下: -

alter index my_index_name monitoring usage;

然后,您可以通过查询 v$object_usage 来监控该索引是否被使用。可以在Oracle® Database Administrator's Guide中找到有关这方面的信息。

请记住,如果您有一个在更新表之前删除索引然后重新创建它们的仓储策略,您将不得不再次设置索引以进行监视,并且您将丢失该索引的任何监视历史记录。

于 2008-09-26T21:41:10.773 回答
14

在数据仓库中,拥有大量索引是很常见的。我使用过具有 200 列和其中 190 列的事实表。

尽管这有开销,但必须在上下文中理解,在数据仓库中,我们通常只插入一次行,我们从不更新它,但它可以参与数千个 SELECT 查询,这些查询可能受益于任何列。

为了获得最大的灵活性,数据仓库通常使用单列位图索引,除了高基数列,可以使用(压缩)btree 索引。

索引维护的开销主要与写入大量块和块拆分的费用有关,因为新行添加了该列现有值范围“中间”的值。这可以通过分区和使新数据负载与分区方案保持一致以及使用直接路径插入来缓解。

为了更直接地解决您的问题,我认为首先索引显而易见的内容可能很好,但不要害怕添加更多索引来确定对表的查询是否会受益。

于 2008-09-26T19:37:22.193 回答
12

爱因斯坦关于简单性的解释中,添加尽可能多的索引,而不是更多。

然而,说真的,只要将数据添加到表中,您添加的每个索引都需要维护。在主要是只读的表上,大量索引是一件好事。在高度动态的表上,越少越好。

我的建议是涵盖常见和明显的情况,然后当您遇到需要更快地从特定表中获取数据的问题时,评估并添加索引。

此外,每隔几个月重新评估您的索引方案是一个好主意,只是看看是否有任何新的需要索引或您创建的任何索引没有被用于任何事情并且应该被摆脱.

于 2008-09-26T18:56:33.757 回答
6

除了其他人提出的观点之外,如果有更多索引,则基于成本的优化器在为 SQL 语句创建计划时会产生成本,因为要考虑的组合更多。您可以通过正确使用绑定变量来减少这种情况,以便 SQL 语句保留在 SQL 缓存中。然后,Oracle 可以进行软解析并重新使用它上次找到的计划。

一如既往,没有什么是简单的。如果涉及倾斜的列和直方图,那么这可能是一个坏主意。

在我们的网络应用程序中,我们倾向于限制我们允许的搜索组合。否则,您必须逐字逐句地测试每个组合的性能,以确保您没有某个人有一天会发现的潜在问题。我们还实施了资源限制,以防止出现问题时在应用程序的其他地方引起问题。

于 2008-10-08T08:19:07.803 回答
6

我对我的真实项目和真实的 MySql 数据库做了一些简单的测试。我已经在这个主题中回答了:索引多个 db 列的成本是多少?

但我认为如果我在这里引用它会更好:

我使用我的真实项目和真实的 MySql 数据库做了一些简单的测试。

我的结果是:将平均索引(索引中的 1-3 列)添加到表中 - 使插入速度降低 2.1%。因此,如果您添加 20 个索引,您的插入速度会降低 40-50%。但是您的选择会快 10-100 倍。

那么添加很多索引可以吗?- 这取决于:) 我给了你我的结果 - 你决定!

于 2010-02-08T00:51:56.347 回答
3

最终,您需要多少索引取决于您在数据库服务器上运行的应用程序的行为。

一般来说,插入越多,索引就越痛苦。每次执行插入时,都必须更新包含该表的所有索引。

现在,如果您的应用程序有相当多的读取量,或者甚至更多,如果它几乎是所有读取量,那么索引就是要走的路,因为将以很少的成本实现重大的性能改进。

于 2008-09-26T18:54:11.843 回答
3

我认为没有静态答案,这类事情属于“性能调整”。

可能是您的应用程序所做的一切都是通过主键查找的,或者可能是相反的,因为查询是在不受限制的字段组合上完成的,特别是任何一个都可以在任何给定时间使用。

除了索引之外,还有重新组织您的数据库以包括计算的搜索字段、拆分表等 - 它实际上取决于您的负载形状和查询参数,查询需要“真正”返回多少/什么数据。

如果您的整个数据库前面是存储过程门面,那么转向会变得更容易一些,因为您不必担心每个临时查询。或者您可能对将访问您的数据库的查询类型有深入的了解,并且可以将调整限制在这些查询范围内。

对于 SQL Server,我发现数据库引擎优化顾问很有用——您可以设置“典型”工作负载,它可以就添加/删除索引和统计信息提出建议。我确信其他数据库也有类似的工具,无论是“官方”还是第三方。

于 2008-09-26T18:57:19.217 回答
3

这确实是一个比实际更理论的问题。索引对性能的影响取决于您拥有的硬件、Oracle 的版本、索引类型等。昨天我听说 Oracle 宣布了由 HP 制造的专用存储,它应该在 11g 数据库上运行速度提高 10 倍。至于您的情况,可以有几种解决方案: 1.拥有大量索引(> 20)并每天(每晚)重建它们。如果表每天有数千次更新/删除,这将特别有用。2. 对您的表进行分区(如果这适用于您的数据模型)。3. 为新的/更新的数据使用单独的表,并运行一个将数据组合在一起的每晚进程。这将需要更改您的应用程序逻辑。4. 如果您的数据支持,切换到 IOT(索引组织表)。

当然,这种情况可能有更多的解决方案。我给你的第一个建议是将数据库克隆到开发环境,并对其进行一些压力测试。

于 2008-09-26T18:58:23.287 回答
2

如果您主要阅读(并且很少更新),那么真的没有理由不索引您需要索引的所有内容。如果您经常更新,那么您可能需要谨慎对待您拥有的索引数量。没有硬性数字,但是当事情开始放缓时,您会注意到。确保您的聚集索引是基于数据最有意义的索引。

于 2008-09-26T18:54:52.623 回答
2

您可能会考虑的一件事是构建索引以针对标准搜索组合。如果经常搜索 column1,并且经常将 column2 与它一起使用,并且 column3 有时与 column2 和 column1 一起使用,那么在 column1、column2 和 column3 上按该顺序排列的索引可以用于这三种情况中的任何一种,尽管它是只需要维护一个索引。

于 2008-09-26T18:55:57.223 回答
2

更新基础表时,索引会产生成本。索引在用于加速查询时提供了好处。对于每个索引,您需要平衡成本与收益。如果没有索引,查询会慢多少?跑得更快有多大好处?当索引丢失时,您或您的用户能否容忍缓慢的速度?

您能容忍完成更新所需的额外时间吗?

您需要比较成本和收益。这对你的情况来说是特别的。没有超过“太多”阈值的索引数量。

还有存储索引所需的空间成本,但您已经说过在您的情况下这不是问题。在大多数情况下也是如此,因为磁盘空间变得如此便宜。

于 2008-09-26T19:02:59.780 回答
1

有多少列?我一直被告知要制作单列索引,而不是多列索引。所以没有比列数更多的索引,恕我直言。

于 2008-09-26T18:55:36.770 回答
1

真正归结为,不要添加索引,除非您知道(这通常意味着收集使用统计信息)它的使用频率将远远超过更新频率。

任何不符合该标准的索引都将花费您更多的重建成本,而不是在使用它的奇怪情况下不使用它的性能损失。

于 2008-09-26T18:56:33.260 回答
1

Sql server 为您提供了一些很好的工具,可以让您查看实际使用了哪些索引。这篇文章http://www.mssqltips.com/tip.asp?tip=1239为您提供了一些查询,让您可以更好地了解索引的使用量,而不是更新量。

于 2010-02-16T17:59:45.500 回答
0

它完全基于 Where 子句中使用的列。作为规则的拇指,我们必须在外键列上建立索引以避免死锁。AWR 报告应定期分析以了解索引的需求。

于 2010-09-26T12:27:00.160 回答