我最近参与了一个使用SQL Server 2000进行数据存储的新软件项目。
在审查项目时,我发现其中一个主表在其主键上使用聚簇索引,该索引由四列组成:
Sequence numeric(18, 0)
Date datetime
Client varchar(9)
Hash tinyint
此表在正常操作过程中经历了大量插入。
现在,我是一名C ++开发人员,而不是数据库管理员,但我对此表设计的第一印象是,将这些字段作为聚簇索引对插入性能非常不利,因为数据必须是在每个插页上进行物理重新排序。
此外,我无法真正看到任何好处,因为人们必须经常查询所有这些字段以证明聚簇索引的合理性,对吧?
所以基本上我需要一些弹药才能让我们相信它们可以让他们相信桌面设计应该改变。
答案 0 :(得分:16)
答案 1 :(得分:5)
群集索引(CI)在不断增加的,狭窄的,很少变化的值上工作得最好。您希望您的CI涵盖使用> =,< =或BETWEEN语句在查询中最常出现的列。
我不确定您的数据通常会如何受到影响。大多数情况下,您会在IDENTITY列或其他窄列上看到CI(因为此列也将“粘贴”到所有非聚集索引上,并且我们不希望每次获取都添加大量数据如果不需要)。有可能数据可能在日期最常被查询,这可能是一个不错的选择,但所有四列可能不正确(我可能会强调,因为我不知道该集合 - up;这可能没有任何问题)。这里有一些指示:http://msdn.microsoft.com/en-us/library/aa933131%28SQL.80%29.aspx
答案 2 :(得分:2)
有些事情你误解了SQL如何创建和使用索引。
聚簇索引aren't necessarily physically ordered on disk by the clustered index,至少不是实时的。它们只是一种逻辑排序。
在实际发现与该索引相关的性能问题之前,我不希望基于此结构的主要性能损失和删除聚簇索引显然是过早优化。
此外,索引可能很有用(尤其是包含多个字段的索引),即使对于未对其中包含的所有列进行排序或查询的搜索也是如此。
显然,创建一个多部分聚集索引应该有理由,就像任何索引一样,所以如果你认为它是反复无常的,那么就有必要提出这个问题。
结论:在实际检测到插入的性能问题之前,请不要优化插入性能的索引。它通常是不值得的。
答案 3 :(得分:1)
如果您的表上只有那个单独的聚簇索引,那可能不会太糟糕。但是,聚簇索引还用于查找非聚集索引中任何命中的实际数据页 - 因此,聚簇索引(其所有列)也是您可能拥有的每个非聚簇索引的一部分。你的桌子。
因此,如果你的桌子上有一些非聚集索引,那么你肯定是a)浪费了大量空间(而不仅仅是在磁盘上 - 也在你服务器的RAM中!)b)你的表现会很糟糕
一个好的聚集索引应该是:
我敢打赌,如果没有更多这些要求,你当前的设置至少会违反两个。不遵循这些建议将导致浪费空间,正如您所说,许多页面和索引碎片和页面拆分(当插入发生在聚集索引中间的某处时,必须“重新排列”数据)。
老实说:只需在代表中添加一个代理ID INT IDENTITY(1,1)
并将其作为主群集密钥 - 如果你有很多INSERT(和UPDATE),你应该会看到相当不错的性能提升正在进行中!
在此处查看更多背景信息,了解什么是良好的群集密钥,以及它们的重要性:
答案 4 :(得分:0)
我最终同意Erik的最后一段:
“归根结底,这一切都取决于确切的系统及其独特的数据访问模式,以及关于您希望优化哪些部分的决策......”
这是我迫使人们学习的基本内容:没有通用解决方案。
您必须知道您的数据以及针对它执行的操作。您必须知道不同类型的操作的频繁程度及其影响和预期的执行时间(如果最终用户同意查询执行时间不那么重要,您不必对一些很少执行的查询进行硬调并影响其他所有操作 - 假设每周等待一些报告几分钟就可以了。当然,正如Erik所说
“性能不仅仅与用户等待时间甚至查询响应时间有关,还与服务器资源有关”
如果此类查询影响整体服务器性能,则应将其视为优化的重要候选者,即使执行时间正常也是如此。我已经看到一些非常快速的查询在多处理器服务器上使用了大量的CPU,而稍微慢一点的解决方案从资源利用的角度来看是无比的“更轻”。在那种情况下,我几乎总是选择较慢的一个。
一旦你知道你的目标是什么,就可以决定你需要多少个索引以及应该聚集哪个索引。唯一约束,过滤索引,包含列的索引是非常强大的调优工具。选择合适的列很重要,但通常选择正确的列顺序更为重要。最后,如果经常修改表,请不要使用大量索引来终止插入/更新性能。