19

我想优化我的团队用于应用程序的数据库的性能。

我一直在寻找添加外键的区域,然后索引这些列以提高连接的性能。但是,我们的许多表都连接在一个GUID类型的 id 上,该类型是在插入项目时生成的,并且在其他表中与该项目关联的数据通常具有item_id包含 GUID 的列。

我已经读过将聚集索引添加到 GUID 类型列是一个非常糟糕的决定,因为索引需要不断重建才能有效。但是,我想知道,在上述场景中使用非聚集索引是否有任何损害?或者假设它会有助于提高性能是否合理?如果需要,我可以提供更多信息。

4

5 回答 5

24

到目前为止,a 上的索引<anytype>是改进连接和单例查找的最佳选择。缺少此索引,查询将始终必须端到端扫描整个表,而(通常)性能结果很糟糕,并发性会被淘汰。

由于您提到的原因,确实uniqueidentifier对索引做出了糟糕的选择,但这绝不意味着您不应该创建这些索引。如果可能,建议将数据类型更改为 INT 或 BIGINT。使用NEWSEQUENTIALID()UuidCreateSequential生成它们将有助于解决碎片问题。如果所有替代方案都失败了,您可能需要比其他索引更频繁地执行索引维护(重建、重组)操作。但绝不是这些缺点中的任何一个都超过了首先拥有索引的好处!

于 2012-12-10T15:45:14.183 回答
5

两种表现:
-插入
-选择

索引应该改进选择

索引会减慢插入速度。
如果插入是有序的,则索引不会分段。
如果插入不按顺序排列,则索引将分片。
索引碎片会减慢插入和选择的速度。
通过维护可以对索引进行碎片整理。

向引用 FK 的列添加非聚集索引将有助于连接。
由于该列很可能没有排序,因此它是一个 GUID 是没有损失的。

在 FK 表本身上,GUID 不适合 PK(聚集索引)。
使用 GUID 作为 PK,在插入时索引片段。
整数或顺序 ID 是更好的候选者,因为它们不会在插入时分割 PK。
但没什么大不了的,只是对这些表进行碎片整理。

于 2012-12-10T15:25:12.510 回答
2

是的,最好将 Guid 索引从集群更改为非集群。Guid 仍然可以是主键,您无需更改查询/源代码。无需重新排序数据并提高性能。

在 SQL Azure 等数据库中,必须有一个聚集索引。所以你可以使用日期/日期时间字段。创建额外的 int-identity/autoincrement 列是不必要的,因为一个团队中的一些开发人员倾向于使用这些和其他 GUID。导致应用不一致。所以只保留 GUID .. 句号!

谈到顺序 Guid,我认为从代码创建 Guid 比从数据库创建 Guid 更好。现代 DAL 和存储库模式不喜欢依赖 DB for CRUD。例如场景:linq 查询和具有单元测试的自动构建,不依赖数据库。并且我们自己创建一个顺序引导不是一个好主意(至少对我来说)。所以 Guid 作为具有非聚集索引的主键是最好的选择。

I have backing from Microsoft on the non-clustered subject http://blogs.msdn.com/b/sqlazure/archive/2010/05/05/10007304.aspx

Edited: Backing is gone ("No Resource Found")

于 2013-11-24T10:47:43.053 回答
1

它通常会帮助性能。但是您可能希望创建填充因子小于 100% 的索引,这样不可避免的页面拆分就不必经常发生。对索引进行定期维护肯定是一个加分项。

于 2012-12-10T15:01:07.677 回答
0

是的,非聚集索引非常适合您的情况。底层是B-tree,和聚簇索引一样,但是表上的底层数据没有排序,所以不存在GUID非顺序性的问题。NC 索引与表分开存在。

但请注意不要添加太多非聚集索引。仅在需要的地方进行优化。运行分析器以查看哪些查询需要很长时间,并仅优化那些。此外,请确保将填充因子设置为 <50% 的值,除非数据库很少获得任何更新,或者空间是一个约束。

相关 MSDN: http: //msdn.microsoft.com/en-us/library/ms177484 (v=sql.105).aspx

于 2012-12-10T15:00:54.307 回答