Ускорение триггера обновления для представления - PullRequest
0 голосов
/ 17 февраля 2011

У нас много взаимно-однозначных отношений в довольно большой базе данных. Коллега создал представление, чтобы собрать всю эту информацию в одну область для использования в качестве единого объекта в нашем .NET-проекте.

Представление имеет триггеры вставки, обновления и удаления, которые все работают хорошо, единственная проблема - это обновление, выполнение которого занимает ~ 7 секунд, что слишком долго. Поскольку база данных очень хорошо проиндексирована (хотя представление и нет), я считаю, что проблема заключается в том, как выполняется представление

Структура триггера обновления выглядит следующим образом:

update table1 set col1 = i.col1, col2 = i.col2 .....
from inserted i
inner join table1 t1 on i.id = t1.id

update table2 set col1 = i.t2_col1, col2 = i.t2_col2......
from inserted i
inner join table2 t2 on i.id = t2.t1Id

if @@rowcount = 0 begin

insert table2 (t1Id, col1, col2....)
select i.t1Id, i.t2_col1, i.t2_col2..... from inserted i

end

/* There are an additional 9 update .... if @@rowcount = 0 insert statements */

Таким образом, я понимаю, что независимо от того, какое свойство обновляется, все операторы обновления выполняются, что вызывает проблему с производительностью.

Я перехожу к тому факту, что нам придется переписать слой доступа к данным, чтобы избавиться от этого представления, но я подумал, что я спросил, есть ли какие-либо предложения на основе SQL о том, как ускорить этот триггер вверх

Любая помощь будет принята с благодарностью

Ответы [ 4 ]

1 голос
/ 09 июня 2011

Где вы говорите:

независимо от того, какое свойство обновляется, все операторы обновления выполняются

В триггере sqlserver вы можете сделать что-то вроде

IF UPDATE(Col1)
BEGIN
  -- do col1 specific updates
END

См. Документацию триггера создания: http://msdn.microsoft.com/en-us/library/ms189799%28v=SQL.90%29.aspx

Также, когда вы говорите «хорошо проиндексированный», заметьте, что индексы ускоряют запросы, но замедляют обновления

1 голос
/ 17 февраля 2011

Ну, не зная точно, что вы делаете, трудно сказать.Я хотел бы представить, что вы могли бы добавить некоторые предложения where к этим операторам обновления, чтобы обновления выполнялись только при определенных условиях.Вы также можете потенциально обернуть операторы обновления в некоторые операторы if и проверить вставленные записи (записи) с ордерами на запуск обновления.Вы также можете потенциально индексировать представление, чтобы ускорить процесс.

0 голосов
/ 13 ноября 2015

Немного опоздал на вечеринку, но я понял (трудным путем), что псевдотаблицы inserted и deleted - странные звери; особенно, когда объем данных растет.

Поскольку вы не можете реально индексировать их или добавлять к ним статистику (AFAIK), планы запросов часто используют неоптимальный подход при работе с имеющейся там информацией. Иногда это действительно помогает извлечь соответствующие данные из этих псевдотаблиц в # temp-таблицы и работать оттуда. Поскольку в этом случае похоже, что таблица inserted используется снова и снова в поле id, может быть полезно работать с таблицей # temp, имеющей индекс в поле id.

Дальнейшее чтение: Медленное соединение на вставленных / удаленных триггерных таблицах

0 голосов
/ 17 февраля 2011

Иногда я обнаружил, что если вы «указываете очевидное» на SQL Server, он может работать лучше. То есть, если вы скажете ему делать обновление, только если есть что изменить. Например, где у вас есть:

update t1 set col1 = i.col1, col2 = i.col2 .....
from inserted i
inner join table1 t1 on i.id = t1.id

Вы можете добавить условие where:

where t1.col1 <> i.col1 or t1.col2 <> i.col2 ...

(при условии, что все столбцы не обнуляются - в противном случае вам нужно больше проверок). Может быть стоит посмотреть, получишь ли ты от этого выгоду.


Если у вас есть пустые столбцы, для каждого такого столбца вам нужно выполнить 3 проверки, например так:

where
  (t1.col1 <> i.col1 or (t1.col1 is null and i.col1 is not null) or (t1.col1 is not null and i.col1 is null)) or 
  (t1.col2 <> i.col2 or (t1.col2 is null and i.col2 is not null) or (t1.col2 is not null and i.col2 is null)) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...