Использует ли ALTER INDEX ALL REBUILD больше места в журнале транзакций с простой моделью восстановления, чем при перестройке каждого индекса по отдельности?

18

Операция «ALTER INDEX ALL REBUILD» в SQL Server 2012 завершилась неудачно, поскольку в журнале транзакций не хватило места. Индексы никогда не реорганизовывались и не перестраивались, поэтому фрагментация составляет более 80% почти по всем из них.

БД использует простую модель восстановления. Я предполагал, что после каждой операции с индексом, выполняемой формой «ВСЕ» команды, данные журнала транзакций будут сбрасываться до следующей перестройки индекса. Так ли это на самом деле, или перестройки индекса записываются так, как будто они являются частью одной транзакции?

Другими словами, могу ли я уменьшить рост журнала транзакций, написав скрипт для выполнения каждой перестройки в отдельности? Есть ли другие факторы, которые следует учитывать?

Google Fail
источник
2
Если не использовать явные данные, я бы предположил, что конкретная команда SQL будет рассматриваться как единая атомарная транзакция механизмом БД. В этом случае вы можете довольно легко проверить теорию. Возьмите свой самый большой индекс и попробуйте просто восстановить его. Если это успешно, то разумно предположить, что журнал накапливает информацию из нескольких перестроений. Если это не удается, тогда вам нужно добавить место для журнала (так как у вас возникла проблема в любом случае), или вам нужно попытаться реорганизовать этот индекс, а не перестраивать (если вы не можете увеличить пространство для t- журнал).
RDFozz
Да, эта мысль пришла мне в голову, когда я закончил печатать это (эффект резиновой утки), но я подумал, что было бы лучше получить подтверждение и оставить его другим, кто мог бы думать так же. Я не хочу экспериментировать с этой средой, поэтому я, вероятно, в конечном итоге добавлю место в журналы.
Google Fail

Ответы:

16

Я предполагал, что после каждой операции с индексом, выполняемой формой «ВСЕ» команды, данные журнала транзакций будут сбрасываться до следующей перестройки индекса. Так ли это на самом деле, или перестройки индекса записываются так, как будто они являются частью одной транзакции?

1) Очистка журнала: модель восстановления ПРОСТА не очищает журнал после каждой транзакции, но на контрольных точках. ( ссылка для получения дополнительной информации)

2a) REBUILD ALL: да, REBUILD ALL работает как одна транзакция. Перестройки индекса внутри имеют свои собственные транзакции, но общая операция не завершена до конца. Так что да, вы можете ограничить рост файла журнала, перестраивая отдельные индексы (и, возможно, выполняя команды CHECKPOINT).

2б) Доказательство! Здесь есть демо-скрипт. (Построен в 2016 г.) Сначала создайте тестовую базу данных с таблицей и индексами:

USE master
GO

CREATE DATABASE Test_RebuildLog
GO

ALTER DATABASE Test_RebuildLog
SET RECOVERY SIMPLE
GO

USE Test_RebuildLog
GO

CREATE TABLE IndexTest
(ID int identity(1,1),
a char(1),
b char(1))

CREATE CLUSTERED INDEX CIX_IndexTest_ID ON IndexTest(ID)
CREATE INDEX IX_IndexTest_a ON IndexTest(a)
CREATE INDEX IX_IndexTest_b ON IndexTest(b)

INSERT IndexTest
(a,b)
VALUES ('a','b'),('z','y'),('s','r')

Теперь вы можете сравнить активность журнала между REBUILD ALL и индивидуальной перестройкой

CHECKPOINT
GO
ALTER INDEX ALL ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

CHECKPOINT
GO
ALTER INDEX CIX_IndexTest_ID ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_a ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_b ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

Обратите внимание, что первая открытая транзакция (идентификатор транзакции 0000: 000002fa для меня) не фиксируется до конца REBUILD ALL, но для перестроений с индексом по индексу они фиксируются последовательно.

Форрест
источник
Вау, спасибо за действительно подробный ответ! Это отличный способ увидеть, что происходит под капотом, так сказать.
Google Fail
Красиво объяснил.
Рамакант
4

В настоящее время это единственная транзакция.

Педро Лопес
источник
6
Добро пожаловать в DBA.SE! В целом, лучшие ответы не являются простыми утверждениями, а подкрепляются информацией из документации или статей, или (часто даже лучше) личного опыта, подтверждающего заявленный ответ. Можете ли вы расширить свой ответ, чтобы обеспечить такую ​​поддержку?
RDFozz
2
@RDFozz Справедливый комментарий, но вы смотрели профиль Педро ? Доступ к исходному коду, вероятно, можно считать более авторитетным, чем личный опыт или документация. :-)
Аарон Бертран
3
@AaronBertrand - признаюсь, нет. Я, конечно, думаю, что участие в команде SQL Server действительно подойдет. Тем не менее, это стоит упомянуть в ответе. +1, в любом случае.
RDFozz
3

Вопрос тривиален для восстановления в автономном режиме . Конечно, это одна транзакция. Представьте себе хаос, который может произойти, если операция разделит каждый индекс на свою собственную транзакцию, так как ей придется снять блокировки при фиксации, а затем повторно получить их. Хотя блокировка критической таблицы SCH-M была снята, индексы могут быть отброшены и могут быть созданы новые индексы, как оператор будет обрабатывать такие случаи? Не говоря уже о том, что таблица может быть удалена и даже воссоздана между двумя транзакциями! Включая случай, когда таблица удаляется и создается другая таблица с тем же идентификатором объекта (да, это может произойти) ...

Что, если вы добавите вопрос, чтобы сказать, что произойдет, если перестроение индекса будет перестроено онлайн ? Это одна транзакция или много? Ответ сложен, поскольку в действительности задействовано несколько внутренних транзакций . Тем не менее, ключевым моментом является то, что существует общая транзакция архивирования, которая охватывает всю операцию (оператор ALTER), и это закрепляет журнал на месте (не может усекаться), таким образом, необходимо соответствующим образом запланировать операцию, чтобы обеспечить ~ 1.6x данные размер для режима полного восстановления или 0,2-кратный размер данных для режима BULK_LOGGED / SIMPLE. Смотрите связанные бумаги для более подробной информации.

Вы можете утверждать, что почему автономная сборка не использует те же внутренние транзакции, что и онлайн-режим, и не разделяет операцию? Проблемы, которые я упомянул о том, что таблица изменяется / удаляется между отдельными индексными операциями (т. Е. Таблица «стабильность схемы»), по-прежнему требуют наличия всеобъемлющей транзакции, которая содержит SCH-S в таблице на протяжении всей продолжительности оператора. Поскольку эта транзакция должна содержать SCH-S также во время восстановления, она должна быть записана в журнал, и как таковая будет запись журнала BEGIN XACT, которая закрепит журнал и предотвратит усечение в течение всей продолжительности оператора. Я знаю, что эта конкретная проблема решалась в период времени SQL 2016-2017 (из-за проблем с размером журнала SQL Azure), но я не уверен, какой прогресс был достигнут . Похоже, в предварительном просмотре:Возобновляемое восстановление индекса в открытом доступе для SQL Server 2017 CTP 2.0 .

Ремус Русану
источник
0

Да, у меня была такая же проблема с очень большим столом. Всякий раз, когда я запускал ALTER INDEX ALL, журнал транзакций сильно увеличивался, но если бы он выдавал ALTER INDEX индивидуально, использование пространства журнала было бы меньше.

LT
источник
0

Предыдущий ответ Remus о том, что для онлайн-индексации требуется 1,6-кратный размер индекса в режиме полного восстановления, неверен. Доля пространства журналирования транзакций, необходимая для перестроения индекса онлайн в режиме FULL, может быть намного выше, и мы неоднократно наблюдали размер индекса, особенно когда перестраиваемый индекс сжимается, поскольку журналирование транзакций не сжимается. Уже одно это должно прояснить, что регистрация транзакций во время онлайн-перестроения под FULL может по крайней мере в несколько раз превышать размер индекса. Добавьте в служебную запись записи журнала, которая не полностью документирована Microsoft, но часто оценивается в 60 байт на строку, и пропорциональный размер ведения журнала при перестроении индекса в режиме онлайн при полном восстановлении может во много раз превышать размер перестраиваемого индекса, особенно если индекс сжат

Грег Линвуд
источник
-1

Rdfozz верен, это лучший способ решить, можно ли перестроить ваш самый большой индекс на основе текущего хранилища. Просто запустите, dm_exec_requestsпока происходит операция (или SQL Profiler), чтобы увидеть, перестраиваются ли все индексы. Я также хотел бы рассмотреть вопрос об изменении модели восстановления для массовой регистрации. Это то, что я делаю, и в окне все еще есть резервная копия журнала транзакций. См. Ниже статью https://technet.microsoft.com/en-us/library/ms191484(v=sql.105).aspx

ADTJOB
источник
2
Обратите внимание, что OP заявил, что их БД уже использует ПРОСТУЮ модель восстановления; это только сохраняет транзакции в журнале достаточно долго для завершения транзакций. Не было бы никакого улучшения, если бы они переключились на массовую регистрацию.
RDFozz
Вы совершенно правы. Мои извенения.
ADTJOB