首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >SQL Server 2008+聚集索引的排序顺序

SQL Server 2008+聚集索引的排序顺序
EN

Stack Overflow用户
提问于 2016-12-23 18:12:39
回答 3查看 1.2K关注 0票数 20

SQL Server 2008+聚集索引的排序顺序是否会影响插入性能?

特定情况下的数据类型为integer,插入的值为升序(Identity)。因此,索引的排序顺序将与要插入的值的排序顺序相反。

我的猜测是,它会产生影响,但我不知道,也许SQL Server针对这种情况进行了一些优化,或者它的内部数据存储格式对此无动于衷。

请注意,问题是关于INSERT性能的,而不是关于SELECT的。

更新

为了更清楚地了解这个问题:当要插入的值(integer)的顺序(ASC)与聚集索引(DESC)的顺序相反时会发生什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-01-09 21:44:28

这是有区别的。插入不符合集群顺序的内容会导致大量碎片。

运行以下代码时,DESC聚集索引将在NONLEAF级别生成其他更新操作。

代码语言:javascript
复制
CREATE TABLE dbo.TEST_ASC(ID INT IDENTITY(1,1) 
                            ,RandNo FLOAT
                            );
GO
CREATE CLUSTERED INDEX cidx ON dbo.TEST_ASC(ID ASC);
GO

CREATE TABLE dbo.TEST_DESC(ID INT IDENTITY(1,1) 
                            ,RandNo FLOAT
                            );
GO
CREATE CLUSTERED INDEX cidx ON dbo.TEST_DESC(ID DESC);
GO

INSERT INTO dbo.TEST_ASC VALUES(RAND());
GO 100000

INSERT INTO dbo.TEST_DESC VALUES(RAND());
GO 100000

这两个Insert语句生成完全相同的执行计划,但是在查看操作统计数据时,差异在nonleaf_update_count上显示出来。

代码语言:javascript
复制
SELECT 
OBJECT_NAME(object_id)
,* 
FROM sys.dm_db_index_operational_stats(DB_ID(),OBJECT_ID('TEST_ASC'),null,null)
UNION
SELECT 
OBJECT_NAME(object_id)
,* 
FROM sys.dm_db_index_operational_stats(DB_ID(),OBJECT_ID('TEST_DESC'),null,null)

当SQL使用针对身份运行的DESC索引时,还有一个额外的-under,即正在进行的引擎盖操作。这是因为DESC表正在变得碎片化(在页面开始处插入行),并进行额外的更新以维护B树结构。

关于这个例子,最值得注意的是DESC集群索引变得超过99%的碎片。This is recreating the same bad behaviour as using a random GUID for a clustered index.下面的代码演示了碎片。

代码语言:javascript
复制
SELECT 
OBJECT_NAME(object_id)
,* 
FROM sys.dm_db_index_physical_stats  (DB_ID(), OBJECT_ID('dbo.TEST_ASC'), NULL, NULL ,NULL) 
UNION
SELECT 
OBJECT_NAME(object_id)
,* 
FROM sys.dm_db_index_physical_stats  (DB_ID(), OBJECT_ID('dbo.TEST_DESC'), NULL, NULL ,NULL) 

更新:

在一些测试环境中,我还看到随着page_io_latch_wait_count和page_io_latch_wait_in_ms的增加,DESC表需要等待更多的时间

更新:

出现了一些讨论,当SQL可以执行向后扫描时,降序索引的意义是什么。请阅读这篇关于limitations of Backward Scans的文章。

票数 7
EN

Stack Overflow用户

发布于 2017-01-09 18:12:02

只要数据是按聚集索引排序的(不管它是升序还是降序),那么应该不会对插入性能产生任何影响。这背后的原因是SQL并不关心聚集索引的页面中行的物理顺序。行的顺序保存在所谓的“记录偏移量数组”中,这是唯一需要为新行重写的偏移量数组(不管顺序如何,这都会被重写)。实际的数据行将一个接一个地写入。

在事务日志级别,无论方向如何,条目应该是相同的,因此这不会对性能产生任何额外的影响。通常,事务日志是生成大多数性能问题的日志,但在这种情况下,将不会出现任何问题。

您可以在https://www.simple-talk.com/sql/database-administration/sql-server-storage-internals-101/中找到关于页/行的物理结构的很好的解释。

因此,只要您的插入不会生成页面拆分(如果数据以聚集索引的顺序出现,而不是按照聚集索引的顺序出现),那么您的插入对插入性能的影响将可以忽略不计。

票数 0
EN

Stack Overflow用户

发布于 2017-01-14 04:22:28

基于以下代码,当所选数据按与排序的聚集索引相反的方向排序时,使用排序的聚集索引将数据插入到标识列中会占用更多的资源。

在此示例中,逻辑读取几乎是两倍。

在10次运行之后,排序的升序逻辑读取平均2284和排序的降序逻辑读取平均4301。

代码语言:javascript
复制
--Drop Table Destination;
Create Table Destination (MyId INT IDENTITY(1,1))

Create Clustered Index ClIndex On Destination(MyId ASC)

set identity_insert destination on 
Insert into Destination (MyId)
SELECT TOP (1000) n = ROW_NUMBER() OVER (ORDER BY [object_id]) 
FROM sys.all_objects 
ORDER BY n


set identity_insert destination on 
Insert into Destination (MyId)
SELECT TOP (1000) n = ROW_NUMBER() OVER (ORDER BY [object_id]) 
FROM sys.all_objects 
ORDER BY n desc;

如果您感兴趣,请参阅有关逻辑读取的更多信息:https://www.brentozar.com/archive/2012/06/tsql-measure-performance-improvements/

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41299389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档