2013-03-18 4 views
0

У меня есть следующее заявление:Оптимизировать SQL UPDATE заявление/SqlCommand

UPDATE Table SET Column=Value WHERE TableID IN ({0}) 

У меня есть разделенный запятыми список TableIDs, который может быть довольно длительным (для замены {0}). Я обнаружил, что это быстрее, чем использование SqlDataAdapter, однако я также заметил, что если текст команды слишком длинный, SqlCommand может работать плохо.

Любые идеи?

Это внутри триггера CLR. Каждое выполнение SqlCommand несет какие-то накладные расходы. Я решил, что вышеприведенная команда лучше, чем SqlDataAdapter.Update(), потому что Update() будет обновлять отдельные записи, в результате которых выполняются несколько операторов SQL.

... Я закончил тем, что делал следующее (время запуска пошел от 0,7 до 0,25 секунд)

UPDATE T SET Column=Value FROM Table T INNER JOIN INSERTED AS I ON (I.TableID=T.TableID) 
+0

Не могли бы вы уточнить свой вопрос? Как насчет планов выполнения? – Trinimon

+0

Итак, идентификаторы поступают из таблицы INSERTED. Кажется, я просто ответил на свой вопрос. – 2013-03-18 20:07:30

ответ

0

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

+0

Что такое хорошая длина? Является ли длина текста более важной или число идентификаторов? Будет ли лучше использовать CommandParameters? – 2013-03-18 19:50:24

+0

К сожалению, ответ ... это зависит. Сканирование большой таблицы ужасно для производительности, поэтому правильный ответ - это то, что предотвращает сканирование и позволяет искать. Это действительно зависит от избирательности столбца, который вы фильтруете в разделе where. Длина не имеет большого значения, количество элементов более важно. Я рекомендую пробную версию и ошибку, чтобы определить, что лучше для вас. –

0

Возможно, разделите свой список идентификаторов в партии. Я предполагаю, что у вас есть список идентификационных номеров в коллекции, и вы создаете строку {0}. Так что, возможно, обновите 20 или 100 за раз.

Заверните его в транзакции и выполнять все обновления перед вызовом Commit()

0

Если вы можете использовать хранимую процедуру, можно использовать MERGE заявление вместо этого.

MERGE INTO Table AS target 
USING @TableIDList AS source 
ON target.TableID = source.ID 
WHEN MATCHED THEN UPDATE SET Column = source.Value 

где @TableIDList будет table type отправлено из кода как табличное значение параметра с ID с (и, возможно, Value с) вам нужно.

0

Если это хранимый метод, я бы использовал параметр Table-Valued Parameter. Если это специальная партия, тогда рассмотрите возможность заполнения временной таблицы и присоединения к ней в вашей партии. Ваш IN-предложение рационализируется как совокупность OR, которая может довольно легко отрицать использование индекса. С помощью JOIN вы можете получить лучший план от оптимизатора.

DECLARE @Value VARCHAR(100) = 'Some value'; 
CREATE TABLE #Table (TableID INT PRIMARY KEY); 
INSERT INTO #Table VALUES (1),(2),(3),(n)...; 
MERGE INTO Schema.Table AS target 
USING #Table AS source 
ON target.TableID = source.TableID 
WHEN MATCHED THEN UPDATE SET Column = Value; 
Смежные вопросы