Sql server 为什么在更新未包含在索引中的视图值时,会更新视图上的聚集索引并重新排序?

Sql server 为什么在更新未包含在索引中的视图值时,会更新视图上的聚集索引并重新排序?,sql-server,tsql,Sql Server,Tsql,我有table属性: attributeId INT IDENTITY, entity NVARCHAR(150) NOT NULL, rank INT NOT NULL, label NVARCHAR(500) NOT NULL, CONSTRAINT pk_attribute PRIMARY KEY CLUSTERED (attributeId) 表AttributeValue: attributeId I

我有table属性:

attributeId     INT IDENTITY,
entity          NVARCHAR(150) NOT NULL,
rank            INT NOT NULL,
label           NVARCHAR(500) NOT NULL,
CONSTRAINT pk_attribute PRIMARY KEY CLUSTERED (attributeId)
表AttributeValue:

attributeId         INT NOT NULL,
entityId            INT NOT NULL,
value               SQL_VARIANT NOT NULL,
CONSTRAINT pk_attributeValues PRIMARY KEY CLUSTERED (attributeId, entityId),
所以我提出了一个观点:

CREATE VIEW dbo.vw_attributevalues
WITH SCHEMABINDING, VIEW_METADATA
AS
    SELECT  a.entity, av.entityId, a.attributeId, av.value,
            a.rank, a.label,
    FROM    dbo.attribute a
    JOIN    dbo.attributeValue v
            ON a.attributeId = v.attributeId
GO

CREATE UNIQUE CLUSTERED INDEX idx_vw_attributevalues_for_entity_entityId
    ON dbo.vw_attributevalues (entity, entityId, attributeId) WITH (DATA_COMPRESSION = PAGE);
GO
当我更新排名(不在索引中)时,它会更新索引并对其重新排序:

UPDATE dbo.attribute
SET rank = 25000
WHERE attributeId = 100011;


这部分费用很高。我不明白为什么sql server会重新排序和更新索引

由于索引视图是物化的,因此当更新视图中引用的任何物化对象时,该视图上的关联索引也会更新。在创建索引视图时,这是一个非常重要的考虑因素

Per:

在被大量索引表引用的表上执行DML1时 视图,或更少但非常复杂的索引视图 索引视图也必须更新。因此,DML查询 性能可能会显著降低,或者在某些情况下,查询计划会降低 甚至不能生产。在这种情况下,测试您的DML查询 在生产使用之前,分析查询计划并调整/简化 DML声明

例如更新、删除或插入操作

更新dbo.attribute时,您正在更新两个索引:pk_attribute和idx_vw_attributevalues_for_entity_entityId。idx_vw_attributeValue_for_entity_entityId使用三列群集键,其中包括
entity
,一个NVARCHAR(150)列。根据dbo.attribute和dbo.attributeValue中记录的数量,这将是一个代价高昂的更新

请注意以下DDL和执行计划:

-- sample data
CREATE TABLE dbo.a(c INT PRIMARY KEY CLUSTERED);
CREATE TABLE dbo.b(c INT PRIMARY KEY CLUSTERED);
INSERT dbo.a(c) VALUES(1),(2),(3);
INSERT dbo.b(c) VALUES(1),(2),(5);
GO

-- Sample indexed view
CREATE VIEW dbo.vw_ab
WITH SCHEMABINDING AS
SELECT ac = a.c, bc = b.c
FROM   dbo.a
JOIN   dbo.b ON a.c < b.c;
GO
CREATE UNIQUE CLUSTERED INDEX uq_dbo_vw_ab ON dbo.vw_ab(ac, bc);
GO
-- Inserts:
INSERT dbo.a(c) VALUES(20);
INSERT dbo.b(c) VALUES(50);
执行计划:


为了更好地理解更新/插入/删除成本高昂的原因,请通过删除不同的索引、添加/修改数据,然后比较有无索引的影响来开始测试。我怀疑NVARCHAR(150)专栏是你在这里被杀的原因

当你说“重新排序”时,我假设你指的是输出数据行的顺序?您没有
orderby
子句。如果没有明确的订单,订单永远无法得到保证。我想我应该使用“排序”这个词,它更准确。我的行刑计划是法语的。“Trier”是指“sort”。因此,当我编写reorder时,我的意思是在执行计划中更新之前对索引进行排序。我明白了吗?(对不起,我是土生土长的法国人)。好的,非常感谢!!!此外,在我的视图中,属性中有更多的列,但我想简化我的问题。所以我认为你是对的。我现在考试。