Медленное обновление (первичный ключ) - PullRequest
1 голос
/ 14 июля 2009
update auditdata set TATCallType='12',TATCallUnit='1' from auditdata auditdata 
        inner join Auditdata_sms_12 a_sns
        on auditdata.ID = a_sns.id

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

что не так в этом

Auditdata.ID - это первичный ключ.

если я запускаю команду обновления, это также обновляет индексы ??? это причина получения обновления медленно

Ответы [ 4 ]

2 голосов
/ 14 июля 2009

Здесь есть пара вещей.

Во-первых, оператор SQL выглядит неработающим. Предложение "FROM" в обновлении предназначено для использования в качестве обновления JOIN'd. Поскольку вы обновляете строки жестко закодированными значениями, делать это не нужно.

Во-вторых, и более эзотерически, если все индексы верны, как вы говорите, то, возможно, вы имеете дело с медленным дисковым вводом-выводом для начальной записи или для области журнала транзакций (отмена в Oracle, журналы в SQL Server и т. д.).

В качестве проверки здравомыслия я бы сделал две вещи. Во-первых, обновлять только те строки, для которых еще не установлены условия. Многие продукты СУБД с удовольствием выполнят физический дисковый ввод-вывод для строки, которая не изменяется (хотя многие этого не делают). Попробуй с лимитом.

Два, примените обновление небольшими партиями. Это может действительно помочь с конфликтами журналов и с более медленными дисками.

Итак, сначала нужно попробовать что-то вроде следующего:

UPDATE auditdata 
   SET TATCallType = '12' 
     , TATCallUnit = '1' 
  FROM auditdata 
 WHERE TATCallType <> '12' 
   AND TATCallUnit <> '1'
   AND EXISTS( SELECT *
                 FROM Auditdata_sms_12 a_sns 
                WHERE a_sns.id = auditdata.ID )

Если вы хотите создавать пакеты, в SQL Server это довольно просто:

SET ROWCOUNT 2000

UPDATE ...

(run continually in a loop via T-SQL or by hand until @@ROWCOUNT = 0)

SET ROWCOUNT 0
1 голос
/ 14 июля 2009

Глядя на ваш комментарий, основная таблица содержит меньше строк, чем временная таблица.

Попробуйте использовать предложение EXISTS (или, в некотором смысле, уменьшите сравнение до меньшего числа строк (например, 1500000)

update auditdata set TATCallType='12',TATCallUnit='1' 
from auditdata auditdata 
WHERE EXISTS 
(SELECT id from Auditdata_sms_12 a_sns WHERE a_sns.id = auditdata.ID)

Идея состоит в том, чтобы ограничить сравнения.

РЕДАКТИРОВАТЬ: AuditdataSMS12 должен иметь индекс ID, чтобы можно было быстро получить строку. Это таблица, которую вы действительно ищете для данного идентификатора.

0 голосов
/ 14 июля 2009

Сколько времени занимает простой выбор (например,

 select id from auditdata auditdata 
    inner join Auditdata_sms_12 a_sns
    on auditdata.ID = a_sns.id

) взять и сколько записей он найдет?

Если серверу Sql необходимо прочитать все 5 миллионов записей или обновить миллион записей, и ему не хватает памяти или достаточно быстрого оборудования, то с запросом может не хватить.

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

0 голосов
/ 14 июля 2009

Обновлено После прочтения первоначального запроса я понял, что вы обновляете не поле основного идентификатора, а 2 других поля данных. Пожалуйста, перечитайте первое утверждение моего ответа и прокомментируйте соответственно. К сожалению.

Есть ли кластерный индекс, определенный в любом поле, которое вы обновляете? У кластерных индексов есть свои преимущества, я их не знаю, но они могут привести к значительному снижению производительности во время обновлений. Насколько я понимаю, обновление кластерного индекса может привести к перекомпиляции всего индекса. Если в таблице много данных, это, безусловно, может привести к вашей проблеме.

Кроме того, убедитесь, что на столе нет триггеров. Если есть триггер, который не работает должным образом, это может вызвать тот же удар производительности.

...