Команда DELETE слишком медленная в таблице с кластерным индексом - PullRequest
12 голосов
/ 27 мая 2009

У меня довольно большая таблица с именем FTPLog с записью около 3 млн. Я хотел добавить механизм удаления для удаления старых журналов, но команда удаления занимает много времени. Я обнаружил, что удаление кластерного индекса занимает много времени.

DECLARE @MaxFTPLogId as bigint
SELECT @MaxFTPLogId = Max(FTPLogId) FROM FTPLog WHERE LogTime <= DATEADD(day, -10 , GETDATE())
PRINT @MaxFTPLogId
DELETE FROM FTPLog WHERE FTPLogId <= @MaxFTPLogId

Я хочу знать, как я могу улучшить производительность удаления?

Ответы [ 4 ]

14 голосов
/ 27 мая 2009

Это может быть медленно, потому что большое удаление генерирует большой журнал транзакций. Попробуйте удалить его порциями, например:

WHILE 1 = 1
BEGIN
    DELETE TOP (256) FROM FTPLog WHERE FTPLogId <= @MaxFTPLogId
    IF @@ROWCOUNT = 0
        BREAK
END

Это генерирует меньшие транзакции. И это смягчает проблемы блокировки, создавая передышку для других процессов.

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

7 голосов
/ 27 мая 2009

Так как это таблица журнала, нет необходимости делать кластеризацию.

Маловероятно, что вы будете искать его на Id.

Измените ваш PRIMARY KEY, чтобы он не группировался. Это будет использовать HEAP метод хранения, который быстрее на DML:

ALTER TABLE FTPLog DROP CONSTRAINT Primary_Key_Name
ALTER TABLE FTPLog ADD CONSTRAINT Primary_Key_Name PRIMARY KEY NONCLUSTERED (FTPLogId)

, и просто выдайте:

SELECT @MaxFTPLogTime = DATEADD(day, -10 , GETDATE())
PRINT @MaxFTPLogId
DELETE FROM FTPLog WHERE LogTime <= @MaxFTPLogTime
1 голос
/ 27 мая 2009

Проверьте плотность вашей таблицы (используйте команду DBCC showcontig, чтобы проверить плотность) Плотность сканирования [Best Count: Actual Count] этот параметр должен быть ближе к 100%, а Logical Scan Fragmentation * Параметр 1004 * должен быть ближе к 0% для лучшей производительности вашей таблицы. Если это не так, переиндексируйте и перефрагментируйте индекс этой таблицы, чтобы повысить производительность выполнения вашего запроса.

0 голосов
/ 27 мая 2009

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

Предложение Andomar должно помочь, но я постараюсь почистить его, когда нет вставок.

Альтернатива: когда вы пишете журналы, вы, вероятно, не слишком заботитесь об изоляции транзакций. Поэтому я бы изменил уровень изоляции транзакции для кода / процессов, которые пишут записи в журнале, чтобы вы могли избегать создания огромных tempdb (кстати, проверьте, сильно ли растет tempdb во время этой операции DELETE)

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

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