有多less数据库索引太多?
我正在研究一个Oracle数据库相当大的项目(尽pipe我的问题同样适用于其他数据库)。 我们有一个网页界面,允许用户search几乎任何可能的字段组合。
为了使这些search更快速,我们将索引添加到我们认为用户将通常search的字段和字段组合。 但是,由于我们并不真正了解客户如何使用此软件,因此很难确定要创build哪个索引。
空间不是问题; 我们有一个4TB的RAID驱动器,我们只用了一小部分。 不过,我担心索引太多可能会影响性能。 因为每当添加,删除或修改行时都需要更新这些索引,所以我认为在单个表上创build数十个索引是个不错的主意。
那么有多less指标被认为太多? 10? 25? 50? 或者我应该只覆盖真的,真正普遍而明显的情况,忽略其他一切吗?
这取决于桌子上发生的操作。
如果有大量的SELECT和很less的变化,索引所有你喜欢….这些将(可能)加快了SELECT语句。
如果这个表受到UPDATE,INSERTs + DELETE …的严重打击,那么这些索引将会非常缓慢,因为每次发生这些操作时都需要修改这些索引
话虽如此,你可以明确地添加很多毫无意义的索引到一个不会做任何事情的表。 将B-Tree索引添加到具有2个不同值的列中将毫无意义,因为它不会在查看数据方面添加任何内容。 一列中的值越独特,它将越受益于索引。
我通常是这样的。
- 获取一个典型的日子上的数据上运行的真正的查询日志。
- 添加索引,以便最重要的查询在其执行计划中碰到索引。
- 尽量避免索引具有大量更新或插入的字段
- 经过几个索引,得到一个新的日志,并重复。
与所有的优化一样,当达到要求的性能时,我停止(这显然意味着0点将得到具体的性能要求)。
其他人一直在给你很好的build议。 当你前进的时候,我有一个额外的build议。 在某些时候,你必须做出最佳索引策略的决定。 最后,最好的PLANNED索引策略仍然可以创build最终没有被使用的索引。 一种可以让你find没有使用的索引的策略是监视索引的使用情况。 你这样做如下:
alter index my_index_name monitoring usage;
然后,您可以通过查询v $ object_usage来监视索引是否被使用。 有关这方面的信息可以在Oracle®数据库pipe理员指南中find 。
请记住,如果您在更新表之前有一个删除索引的仓储策略,然后重新创build索引,则必须重新设置索引以进行监视,并且您将失去该索引的任何监视历史logging。
在简单的爱因斯坦的意义上 ,添加尽可能多的索引,你需要和没有更多。
但是,严重的是,每当将数据添加到表中时,您添加的每个索引都需要维护。 在主要只读的表上,大量的索引是一件好事。 在高度dynamic的表格上,越less越好。
我的build议是覆盖常见和明显的情况,然后,当遇到需要从特定表格获取数据的更快速度的问题时,评估和添加索引。
此外,每隔几个月重新评估索引scheme是一个好主意,只是为了查看是否有任何需要索引的新内容或者您创build的任何未被使用的索引,并且应该被删除。
在数据仓库中,拥有大量索引是非常常见的。 我曾与事实表有两百列,其中190个索引。
虽然有一个开销,但是在上下文中必须理解,在数据仓库中,我们通常只插入一行,我们从不更新它,然后它可以参与成千上万的SELECT查询,这些SELECT查询可能受益于索引列。
为了获得最大的灵活性,数据仓库通常使用单列位图索引,除了高基数列以外,可以使用(压缩)的树索引。
索引维护的开销主要与写入大量块的开销相关联,并且随着新行添加了该列的现有值范围的“中间”值的块分割。 这可以通过分区并使新的数据负载与分区schemealignment,并使用直接path插入来缓解。
为了更直接地解决您的问题,我认为首先对显而易见的内容进行索引可能是很好的做法,但是如果对表的查询会受益,则不要害怕增加更多的索引。
除了其他人提出的要点之外,如果有更多的索引,则基于成本的优化器在创buildSQL语句的计划时会产生成本,因为需要考虑更多的组合。 您可以通过正确使用绑定variables来减less这一点,以便SQL语句保留在SQLcaching中。 然后,Oracle可以进行软parsing并重新使用上次find的计划。
一如既往,没有什么是简单的。 如果有歪斜的列和直方图涉及,那么这可能是一个坏主意。
在我们的Web应用程序中,我们倾向于限制我们允许的search组合。 否则,你将不得不从字面上testing每个组合的性能,以确保你没有一个潜在的问题,有人会find一天。 我们还实施了资源限制来阻止这个问题,导致应用程序中的其他地方出现问题。
我对我的真实项目和真正的MySql数据库做了一些简单的testing。 我已经在这个主题中回答了: 索引多个数据库列的成本是多less?
但是我认为如果我在这里引用它会更好:
我用我真正的项目和真正的MySql数据库做了一些简单的testing。
我的结果是:将平均索引(索引中的1-3列)添加到表中 – 使插入速度减慢2.1%。 所以,如果你添加20个索引,你的插入会减慢40-50%。 但是你的select会快10-100倍。
那么可以添加很多索引吗? – 这取决于:)我给你我的结果 – 你决定!
最终,您需要多less个索引取决于您的数据库服务器上的应用程序的行为。
一般来说,插入越多,索引变得越痛苦。 每次执行插入操作时,包含该表的所有索引都必须更新。
现在,如果你的应用程序有很好的阅读量,或者更多,所以如果几乎全部阅读,那么索引是要走的路,因为将会有很大的性能提升,而且成本很低。
如果你主要阅读(和更新),那么真的没有理由不索引你需要索引的一切。 如果你经常更新,那么你可能需要谨慎的索引你有多less。 没有硬数字,但是当事情开始放缓时你会注意到。 确保您的聚集索引是基于数据的最有意义的索引。
你可能会考虑的一件事就是build立索引来定位一个标准的search组合。 如果通常searchcolumn1,并且column2经常与它一起使用,并且column3有时与column2和column1一起使用,则按照该顺序,column1,column2和column3上的索引可以用于这三种情况中的任何一种,尽pipe它是只有一个需要维护的索引。
在我看来,没有一个静态的答案,这种事情属于“性能调整”。
这可能是因为你的应用程序所做的一切都是由主键查找的,也可能是因为查询是通过不受限制的字段组合来完成的,任何特定的时间都可以使用任何特定的字段。
除了索引之外,还有数据库重新编程,包括计算的search字段,拆分表等等 – 它确实取决于你的负载形状和查询参数,查询要重新发送多less/哪些数据。
如果你的整个数据库被存储过程外观所占据,那么转向变得容易一些,因为你不必为每一个特定的查询而烦恼。 或者,您可能会深入了解将会影响您的数据库的查询types,并可能会将调整限制在这些数据库中。
对于SQL Server,我发现数据库引擎优化顾问程序非常有用 – 您设置了“典型”工作负载,并可以提出有关添加/删除索引和统计信息的build议。 我相信其他数据库也有类似的工具,不pipe是“官方”还是第三方。
这实际上是一个比实际更理论化的问题。 索引对你的性能的影响取决于你所拥有的硬件,Oracle的版本,索引types等等。昨天,我听说甲骨文公司宣布了一个由惠普公司制造的专用存储器,这个存储器在11g数据库上应该快10倍。 至于你的情况,可以有几个解决scheme:1.有大量的索引(> 20),并重build他们每天(每晚)。 如果表每天获得数千次更新/删除,这将特别有用。 2.分区你的表(如果这适用于你的数据模型)。 3.为新的/更新的数据使用单独的表格,并运行将数据组合在一起的夜间过程。 这将需要改变你的应用程序逻辑。 4.如果您的数据支持,切换到物联网(索引组织表)。
当然,对于这种情况可能有更多的解决scheme。 我的第一个build议是将数据库克隆到开发环境,并对其进行压力testing。
索引在更新基础表时会产生成本。 索引提供了一个好处,当它被用来加速查询。 对于每个指数,您需要平衡成本与收益。 查询在没有索引的情况下运行慢多less? 运行速度有多大的好处? 您是否可以或者您的用户在索引丢失时容忍低速?
你能容忍额外的时间来完成更新?
你需要比较成本和收益。 这是你的情况特别。 没有超过“太多”阈值的幻数的索引。
存储索引所需的空间也是成本,但是你已经说过,在你的情况下这不是问题。 在大多数情况下也是如此,因为磁盘空间已经变得如此便宜。
那里有多less列? 我一直被告知要做单列索引,而不是多列索引。 所以没有更多的索引比列的数量,恕我直言。
实际上,除非你知道(这通常意味着收集使用统计数据),否则不要添加一个索引,它会比更新更频繁地使用。
任何不符合这个标准的索引都将花费你更多的时间来重build,而不是在奇怪的情况下使用它。
Sql服务器为您提供了一些很好的工具,可以让您查看实际使用的索引。 本文http://www.mssqltips.com/tip.asp?tip=1239为您提供了一些查询,使您能够更好地了解索引的使用情况,而不是更新索引的大小。;
它完全基于Where子句中正在使用的列。 而作为规则的拇指,我们必须在外键列上有索引来避免DEADLOCKS。 AWR报告应定期分析以了解索引的需要。