Почему кластерный индекс в представлении обновляется и переупорядочивается при обновлении значения представления, которое не содержится в индексе? - PullRequest
2 голосов
/ 07 февраля 2020

У меня есть атрибут таблицы:

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

Атрибут таблицы Значения:

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 сервер переупорядочивает и обновляет индекс.

1 Ответ

1 голос
/ 07 февраля 2020

Поскольку индексированное представление материализуется, когда обновляются любые материализованные объекты, на которые есть ссылки в этом представлении, соответствующий индекс в этом представлении также обновляется. Это очень важное соображение при создании индексированных представлений.

Per BOL :

При выполнении DML1 для таблицы, на которую ссылается большое количество проиндексированных представлений или меньшее, но очень сложное проиндексированное представление, те, на которые ссылаются индексированные виды также должны быть обновлены. В результате производительность запросов DML может значительно снизиться, а в некоторых случаях план запроса даже не может быть создан. В таком сценарии ios проверьте свои запросы DML перед производственным использованием, проанализируйте план запросов и настройте / упростите оператор DML.

Такие как операции UPDATE, DELETE или INSERT.

Когда вы обновляете dbo.attribute, вы обновляете два индекса: pk_attribute и idx_vw_attributevalues_for_entity_entityId. idx_vw_attributevalues_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

Здесь мы объединяем dbo.a и dbo.b, затем добавляем индексированное представление. Обратите внимание на план выполнения, при обновлении dbo.a ИЛИ dbo.b я обновляю кластеризованный индекс для каждой таблицы , а также индекс в моем представлении. Обратите внимание на вставки и связанные планы выполнения:

-- Inserts:
INSERT dbo.a(c) VALUES(20);
INSERT dbo.b(c) VALUES(50);

Планы выполнения:

enter image description here

Чтобы лучше понять почему ваши обновления / вставки / удаления являются дорогостоящими, начните тестирование, отбрасывая различные индексы, добавляя / изменяя данные, а затем сравнивая влияние с индексом и без него. Я подозреваю, что колонка NVARCHAR (150) убивает вас здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...