Как удалить записи в SQL 2005, сохраняя журналы транзакций в проверке - PullRequest
4 голосов
/ 09 сентября 2009

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

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

Как сделать хранимую процедуру, описанную ниже, более эффективной, не допуская ненужного увеличения журнала транзакций?

CREATE PROCEDURE [dbo].[ClearLog] 
(
  @Age int = 30
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

  -- DELETE ERRORLOG
  WHILE EXISTS ( SELECT [LogId]  FROM [dbo].[Error_Log] WHERE DATEDIFF( dd, [TimeStamp], GETDATE() ) > @Age )
   BEGIN
    SET ROWCOUNT 10000
    DELETE [dbo].[Error_Log] WHERE DATEDIFF( dd, [TimeStamp], GETDATE() ) > @Age

    WAITFOR DELAY '00:00:01'
    SET ROWCOUNT 0
   END
END

Ответы [ 5 ]

4 голосов
/ 09 сентября 2009

Вот как бы я это сделал:

CREATE PROCEDURE [dbo].[ClearLog] (  
@Age int = 30)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @d DATETIME
        , @batch INT;
    SET @batch = 10000;
    SET @d = DATEADD( dd, -@Age, GETDATE() )
    WHILE (1=1)
    BEGIN
        DELETE TOP (@batch) [dbo].[Error_Log]  
        WHERE [Timestamp] < @d;
        IF (0 = @@ROWCOUNT)
            BREAK
    END
END
  • Сделайте сравнение Tiemstamp SARGable
  • Разделите GETDATE () в начале пакета, чтобы получить последовательный прогон (в противном случае он может блокировать в бесконечном цикле, когда новые записи «возрастают», как удаляются старые).
  • используйте TOP вместо SET ROWCOUNT ( устарело : Using SET ROWCOUNT will not affect DELETE, INSERT, and UPDATE statements in the next release of SQL Server.)
  • проверьте @@ ROWCOUNT, чтобы разорвать цикл вместо избыточного SELECT
1 голос
/ 10 сентября 2009

Если ваша база данных находится в режиме полного восстановления, единственный способ минимизировать влияние ваших операторов удаления - это «удалить их» - удалять только столько в «интервале транзакций». Например, если вы делаете резервные копии t-log каждый час, удаляйте, скажем, только 20 000 строк в час. Это может не отбросить все, что вам нужно, сразу, но все выровняется через 24 часа или через неделю?

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

1 голос
/ 09 сентября 2009

как насчет того, чтобы вы запускали его чаще и каждый раз удаляли меньше строк? Запускайте это каждые 30 минут:

CREATE PROCEDURE [dbo].[ClearLog] 
(
  @Age int = 30
)
AS
BEGIN
    SET NOCOUNT ON;
    SET ROWCOUNT 10000 --I assume you are on an old version of SQL Server and can't use TOP
    DELETE dbo.Error_Log Where Timestamp>GETDATE()-@Age
    WAITFOR DELAY '00:00:01' --why???
    SET ROWCOUNT 0
END

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

1 голос
/ 09 сентября 2009

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

0 голосов
/ 09 сентября 2009

Решение, которое я использовал в прошлом, состояло в том, чтобы временно установить модель восстановления на «Bulk Logged», а затем вернуться к «Full» в конце хранимой процедуры:

DECLARE @dbName NVARCHAR(128);
SELECT @dbName = DB_NAME();

EXEC('ALTER DATABASE ' + @dbName + ' SET RECOVERY BULK_LOGGED')

WHILE EXISTS (...)
BEGIN
    -- Delete a batch of rows, then WAITFOR here
END

EXEC('ALTER DATABASE ' + @dbName + ' SET RECOVERY FULL')

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

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