当前位置:  开发笔记 > 编程语言 > 正文

我应该摆脱Guid列上的聚簇索引

如何解决《我应该摆脱Guid列上的聚簇索引》经验,为你挑选了4个好方法。

我正在研究一个通常使用GUID作为主键的数据库.

默认情况下,SQL Server在主键列上放置聚簇索引.我理解这对于GUID列来说是一个愚蠢的想法,并且非聚集索引更好.

你怎么想 - 我应该摆脱所有聚集索引并用非聚集索引替换它们吗?

为什么SQL的性能调优器不会提供此建议?



1> Mike Woodhou..:

聚簇索引的一个重要原因是您经常要为给定列检索一系列值的行.因为数据按该顺序物理排列,所以可以非常有效地提取行.

像GUID这样的东西,虽然对于主键很好,但可能对性能有积极的影响,因为插入会有额外的成本,并且在选择上没有明显的好处.

所以是的,不要在GUID上集群索引.

至于为什么它不作为推荐提供,我建议调谐器知道这个事实.


使用SQL 2005和newsequentialid(),碎片问题在很大程度上消失了.最好通过查看sys.dm_db_index_physical_stats和sys_indexes进行测量.

2> Charles Bret..:

您几乎肯定希望在数据库中的每个表上建立聚簇索引.如果表没有聚簇索引,那么它就是所谓的"堆",并且大多数类型的公共查询的性能对于堆而言比对聚簇索引表的性能要低.

应建立聚簇索引的字段取决于表本身,以及针对表的查询的预期使用模式.在几乎每种情况下,您可能希望聚簇索引位于列或唯一的列组合上,即(备用键),因为如果不是,SQL将在任何结尾处添加唯一值无论如何你选择的字段.如果您的表中有一列或多列,查询将经常使用这些列来选择或过滤多个记录(例如,如果您的表包含销售交易,您的应用程序将经常按产品ID请求销售交易,甚至更好,发票明细表,几乎在每种情况下,您都将检索特定发票的所有明细记录,

这些列是聚集索引的候选列.聚簇索引中列的顺序很重要.索引中定义的第一列应该是在预期查询中首先选择或筛选的列.

所有这一切的原因是基于理解数据库索引的内部结构.这些索引称为平衡树(B-Tree)索引.它们有点像二叉树,除了树中的每个节点都可以有任意数量的条目(和子节点),而不只是两个.使聚簇索引不同的原因是聚簇索引中的叶节点是表本身的实际物理磁盘数据页.而非聚集索引的叶节点只是"指向"表的数据页.

因此,当表具有clsutered索引时,表数据页是该索引的叶级,并且每个表都有指向前一页的指针和索引顺序中的下一页(它们形成双向链表) .

因此,如果您的查询请求与聚簇索引具有相同顺序的行范围...处理器只需要遍历索引一次(或可能两次),以查找数据的起始页,然后按照链接列表指针到达下一页和下一页,直到它已经读取了它需要的所有数据页.

对于非聚集索引,它必须为它检索的每一行遍历索引一次...

注意:编辑
要解决Guid Key列的顺序问题,请注意SQL2k5具有NEWSEQUENTIALID(),实际上生成Guids的"旧"顺序方式.

或者您可以调查在客户端代码中实现的Jimmy Nielsens COMB guid algotithm:

COMB Guids


但GUID呢?除非它们是顺序GUID,否则您将永远不会以与聚簇索引相同的顺序检索一系列行.因此我的问题
但是,聚集索引可以帮助查询"组"数据,即使您使用的是非顺序Guids也是如此.例如,如果父表中的guid是PK,并且子表中的复合集群索引PK的第一个(FK)列,则应用所有聚集索引优势.

3> Galwegian..:

GUID字段中的聚簇索引的问题是GUID是随机的,因此当插入新记录时,必须移动磁盘上的大部分数据以将记录插入到表的中间.

但是,对于基于整数的聚簇索引,整数通常是顺序的(与IDENTITY规范一样),因此它们只是添加到末尾,不需要移动任何数据.

另一方面,聚簇索引在GUID上并不总是坏的...这完全取决于应用程序的需求.如果你需要能够SELECT快速记录,那么使用聚集索引...... INSERT速度会受到影响,但SELECT速度会提高.



4> RoadWarrior..:

虽然在GUID上进行群集通常是一个坏主意,但请注意,即使在非群集索引中,GUID在某些情况下也会导致碎片.

请注意,如果您使用的是SQL Server 2005,则newsequentialid()函数会生成顺序 GUID.这有助于防止碎片问题.

我建议在做出任何决定之前使用如下的SQL查询来测量碎片(借用非ANSI语法):

SELECT OBJECT_NAME (ips.[object_id]) AS 'Object Name',
       si.name AS 'Index Name',
       ROUND (ips.avg_fragmentation_in_percent, 2) AS 'Fragmentation',
       ips.page_count AS 'Pages',
       ROUND (ips.avg_page_space_used_in_percent, 2) AS 'Page Density'
FROM sys.dm_db_index_physical_stats 
     (DB_ID ('MyDatabase'), NULL, NULL, NULL, 'DETAILED') ips
CROSS APPLY sys.indexes si
WHERE si.object_id = ips.object_id
AND   si.index_id = ips.index_id
AND   ips.index_level = 0;

推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有