Удаление с внутренним объединением занимает более 40 секунд, чтобы удалить 500 строк - PullRequest
0 голосов
/ 12 марта 2019

У меня есть этот запрос:

delete L 
from L
inner join M on L.id = M.ref_id 
             or L.id = M.news_id 

И для удаления 588 строк требуется от 39 до 50 секунд.

Выбор выполняется очень быстро 0,015 секунды, если в моем запросе я заменяюdelete L from L от select * from L

Вот мой след в XML

, а вот мой файл плана объяснения .SQLPlan

Надеюсь, вы можете помочь тому, что мне здесь не хватает, в чем здесь проблема?

Ответы [ 2 ]

0 голосов
/ 12 марта 2019

Удаление строк из большой кластеризованной таблицы обычно происходит медленно.

Знаменитый «МЕЖДУ», обсуждаемый в комментариях, является разделом из кластерного индекса, он принимает минимальное и максимальное значения из вашего объединения. Поэтому рекомендуется удалять партиями.

Я думаю, что может быть несколько общих рекомендаций, но это всегда зависит от разных вещей, таких как объем данных, оборудование, память, размер файла журнала и т. д. - Удалить строки в пакетах. Оптимальная партия размер будет зависеть от окружающей среды, но обычно его около 10K 100K. - удалить в порядке кластерного индекса - при возможности включить модель восстановления в BULK / SIMPLE для минимального ведения журнала. - Если возможно удалить ограничения, такие как ограничение внешнего ключа из дочерней таблицы. - Если возможно, отключите некластеризованные индексы - в зависимости от количества данных, которые вы собираетесь удалить, возможно, было бы лучше экспортировать данные в новую таблицу, а затем отбросить старую таблицу или сохранить его с другое имя для дальнейшего использования. Как видите, в основном это будет зависит от ситуации и окружающей среды.

Это лучший ответ: «Возможно, вам нужно настроить систему, а не запрос»

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

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

источник: https://ask.sqlservercentral.com/questions/90223/how-to-reduce-the-cost-of-clustered-index-delete.html

0 голосов
/ 12 марта 2019

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

DECLARE @temp TABLE
(
    id int
);

INSERT INTO @temp
SELECT id
from L
inner join M on L.id = M.ref_id 
         or L.id = M.news_id;

DELETE FROM L WHERE id IN (SELECT id FROM @temp)
...