【发布时间】:2014-01-22 03:25:32
【问题描述】:
经过 20 年的专业发展,我仍然发现自己对数据库性能的某些方面一无所知。这是其中之一。关于表和索引碎片及其对性能的影响,这里和其他地方有成千上万的问题。我知道基本的注意事项,但有时似乎没有“好的”答案。这是我的问题,我经常遇到它:
表仅用于存储定义一对多关系的 id 对,让我们以朋友为例。 Friends 表仅包含 personId (int)、friendId (int)。每对当然都是独一无二的。 (因此,但可能与问题无关,每个关系的逆对也存在。)因此数据的一个非常小的样本将是:
1001, 1011
1001, 1012
1001, 1013
1011, 1001
1012, 1001
1013, 1001
etc...
个人 1001 有 3 个朋友,当然每个朋友都有个人 1001 作为朋友,等等。这个表可能有数百万甚至数亿的关系(行),任何给定的人都会可能有数百个朋友。并且它们会被频繁地插入和更新(实际上在这种情况下,删除了一些现有的,添加了新的,没有实际的行更新),并且没有特定的顺序。对于任何给定批次的插入,它们都可以按 personId,friendId 排序,但除此之外,随着时间的推移,插入在很大程度上将是无序的。
此表的用途是查询给定人员的所有朋友,或内部联接到人员查询以分组和聚合与每个人的朋友相关的其他数据等,这是您期望的典型用途一对多关系表。查询性能可能比插入性能更重要,但两者都很重要,因为两者都会经常发生。示例查询:
SELECT p.Name FROM Friends f
INNER JOIN People p ON f.friendId = p.id
WHERE f.personId = @personId
过去,我想都没想就给表一个复合主键personId,friendId,在SQL Server中默认创建为聚集索引,完成用它。但我以前从未处理过如此庞大且对性能至关重要的数据,所以我质疑这个决定。我看不出有任何方式可以以一种不会导致严重且频繁的碎片化的方式来构造这样的表。我的问题是:
有没有更好的方法来构建这些数据?
考虑到聚集索引的两个 int 列代表表中的唯一数据,碎片是否可能像我假设的那样糟糕,如果是这样,这些条件下的碎片是否会导致同样严重我假设的性能受到影响?
(除非我不熟悉 RDBMS 中有一些完全不同的概念,否则我假设第一个问题的答案是否定的。所以这主要是第二个问题,我希望有人有良好的经验基础来回答一下。顺便说一句,如果有区别的话,数据库是 SQL Azure。)
感谢你们中的 DBA 大师,他们提供了一些见解!
【问题讨论】:
-
你需要维护一个索引,不管它是否聚集。据推测,索引需要包含两列(或者您将进行 lot 的 RID 查找),因此它也可能是一个聚集索引。免责声明:不是 DBA。
-
是的,很明显我需要一个索引,无论是否聚集。如果,或者,我给每一行一个顺序标识 id 作为主键/聚集索引,例如relationId,因为插入会经常发生并且不经常删除,所以聚集索引应该保持相对完整,但也永远不会被使用 - 我需要一个关于 personId,friendId 的非聚集索引b>,它会被使用,它会变得非常支离破碎,一事无成,对吧?
-
你明白聚集索引就是表吗?
-
@Namphibian 是的,我知道聚集索引实际上就是表本身。但对其他人来说很好的澄清。
-
@Namphibian 是的,这正是我的意思。
标签: sql sql-server database database-administration