35

“我们应该忘记小的效率,比如大约 97% 的时间:过早的优化是万恶之源。” (唐纳德·克努斯)。我的 SQL 表不太可能每个包含超过几千行(这些都是大行!)。SQL Server 数据库引擎优化顾问认为数据量无关紧要。所以我什至不应该考虑在这些表上放置显式索引。正确的?

4

13 回答 13

39

索引的价值在于加快读取速度。例如,如果您基于日期列中的日期范围执行大量 SELECT,则在该列上放置索引是有意义的。当然,通常你会在你将要加入的任何列上添加索引,并且频率很高。效率增益还与典型记录集的大小与记录数量的比率有关(即,抓取 20/2000 条记录比抓取 90/100 条记录更受益于索引)。对未索引列的查找本质上是线性搜索。

索引的成本来自写入,因为每个 INSERT 还需要对每个列索引进行内部插入。

因此,答案完全取决于您的应用程序——如果它类似于一个动态网站,其中读取次数可以是写入次数的 100 倍或 1000 倍,并且您正在根据数据列进行频繁、不同的查找,那么索引可能是有益的. 但是,如果写入次数大大超过读取次数,那么您的调整应该集中在加快这些查询的速度上。

在 JOIN/WHERE 列上使用和不使用索引来识别和基准测试少数应用程序最频繁的操作需要很少的时间,我建议你这样做。监视您的生产应用程序并识别最昂贵和最频繁的查询,并将优化工作集中在这两组查询的交集上(这可能意味着索引或完全不同的东西,例如为查询或连接缓存)。

于 2008-10-31T08:51:52.013 回答
11

Knuth 的明智之言不适用于创建(或不创建)索引,因为通过添加索引,您并没有直接优化任何内容:您提供的是 DBMS 优化器可以用来优化某些查询的索引。事实上,您最好争辩说,决定不对小表建立索引是过早的优化,因为这样做会限制 DBMS 优化器的选项!

不同的 DBMS 将根据包括表大小在内的各种因素来选择是否对列进行索引,而这些都是应该考虑的。

什么数据库中过早优化的示例:在任何基准测试表明规范化数据库实际上存在任何性能问题之前“为性能而去规范化”。

于 2008-10-31T13:14:41.010 回答
9

将为唯一约束索引主键列。我仍然会索引所有外键列。如果不相关,优化器可以选择忽略您的索引。

如果您只有一点点数据,那么插入/更新的额外成本也不应该很大。

于 2008-10-31T08:46:03.257 回答
7

完全不正确。100% 不正确。不要放置一百万个毫无意义的索引,但您确实需要一个主键(在大多数情况下),并且您确实希望它正确地聚集在一起。

原因如下:

SELECT * FROM MySmallTable <-- No worries... Index won't help

SELECT
    *
FROM
    MyBigTable INNER JOIN MySmallTable ON... <-- Ahh, now I'm glad I have my index.

这是一个很好的规则。

“因为我有一个表,我可能会想在某个时候查询它......如果我要查询它,我可能会以一致的方式这样做......” <- - 这就是你应该如何索引表。

编辑:我正在添加这一行:如果你有一个具体的例子,我会告诉你如何索引它,以及这样做你会节省多少。请提供一张表格,并举例说明您计划如何使用该表格。

于 2008-10-31T09:25:05.580 回答
5

这取决于。该表是参考表吗?

有一千行的表没有索引,并且生成的表扫描可以使相当简单的操作延迟用户 5 分钟而不是 5 秒之间产生差异。我已经看到了这个问题,使用 SQL Server 以外的 DBMS。

通常,如果该表是参考表,则对其进行更新相对较少。这意味着更新索引对性能的影响也相对较少。如果优化器通过索引,优化器的性能影响将可以忽略不计。存储索引所需的空间也可以忽略不计。

如果你声明一个主键,你应该在那个键上获得一个自动索引。该自动索引几乎总是对您有足够的好处来证明其成本是合理的。把它留在那儿。如果您创建一个没有主键的引用表,那么您的设计方法中还有其他问题。

如果您对主键以外的某些列集进行频繁搜索或频繁连接,则额外的索引可能会为自己买单。不要解决这个问题,除非它是一个问题。

这是一般的经验法则:使用 DBMS 的默认行为,除非您找到不这样做的理由。其他任何事情都是您过早地专注于优化。

于 2008-10-31T10:27:55.563 回答
5

我建议您遵循有关索引的通常规则,这大致意味着“在您在查询中使用的那些列上创建索引”。

对于这么小的数据库,这听起来可能没有必要。正如其他人已经说过的那样:只要您的数据库保持与您描述的一样小,查询无论如何都会足够快,并且实际上并不需要索引。它们甚至可以减慢插入和更新的速度,但除非您有非常具体的要求,否则对于这么小的数据库来说并不重要。

但是,如果数据库增长(哪些数据库有时倾向于这样做),您不必记住向那个您可能已经忘记的旧数据库添加索引。也许它甚至已经安装在您的一位客户身上,而您无法修改它!

我想我要说的是:索引应该是数据库设计的自然部分,缺少索引才是优化,无论是否为时过早。

于 2008-10-31T12:25:33.263 回答
3

如果行的宽度很窄,并且几千行适合 10-20 个 8K 页面,那么即使您创建了一个索引,SQL 优化器也不太可能选择使用索引。

于 2008-10-31T08:24:47.463 回答
1

仅在必须
时才放置索引:) 有时放置索引实际上会损害性能,具体取决于表的用途...
因此,换句话说,您会考虑在必要时将索引放在表上,因为通过分析应用程序来确定。

于 2008-10-31T08:26:21.173 回答
1

使用 UNIQUE 约束时,通常会隐式创建索引。在那种情况下,我不会试图避免使用它们!

于 2008-10-31T08:31:07.593 回答
1

作为一般经验法则,最好避免使用较小的索引,因为它们通常不会被使用。

但有时它们可​​以提供巨大的推动力,正如我在这里概述的那样。

于 2008-11-04T01:02:09.380 回答
0

我猜想在表的主键上有一个自动索引,在查询数据较少的表时应该足够了。

所以,是的,如果有一个小数据集需要处理,可以避免显式索引。

于 2008-10-31T08:24:53.737 回答
0

即使您有索引,SQL Server 甚至可能不会使用它,具体取决于该表的统计信息。如果您计划为一年最多运行几次的报告添加索引,请记住,添加索引的 INSERT/UPDATE 惩罚将始终有效。在添加索引之前,问问自己是否值得付出性能代价。

于 2008-10-31T12:45:41.193 回答
0

您必须了解,基于查询可能会进行两次查找,一次进入索引以获取指向该行的指针,另一次进入该行本身。如果正在查询的数据在索引列中,则可能不需要额外的步骤。

即使优化器在索引之后,数据的双重浸入也完全有可能会变慢。我们是否关心取决于应用程序分析和最终解释计划。

于 2009-10-30T03:27:01.777 回答