Какое влияние окажет уменьшение размера столбца varchar на файл базы данных?

15

В нашей базе данных есть несколько таблиц, в которых есть VARCHAR(MAX)столбцы, в которых достаточно VARCHAR(500)(или что-то намного меньше, чем max). Естественно, я хочу очистить их и довести размеры до более разумных уровней. «Как» сделать это, я понимаю: мой вопрос заключается в том, что изменят эти столбцы для страниц и существующих на диске? (Существует много информации о том, что происходит, когда вы увеличиваете столбец, но возникают проблемы с поиском информации о том, что происходит, когда вы уменьшаете столбец.)

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

Заранее спасибо!

РЕДАКТИРОВАТЬ:

У меня есть 20 таблиц, на которые я смотрю, но только у половины из них число строк превышает 1000. Самый большой имеет почти миллион строк. Худшим нарушителем является таблица с 350 000 строк и четырьмя VARCHAR(MAX)столбцами, которые можно сжать до VARCHAR(500)уровня.

nateirvin
источник

Ответы:

12

Перво-наперво: сколько данных в таблице? Количество строк и размер таблицы?

Второе. Можете ли вы создать резервную копию и восстановить эту таблицу на тестовом сервере и выполнить инструкцию alter, чтобы увидеть влияние (если предположить, что оно неосуществимо из-за того, что таблица слишком велика для размещения в непроизводственной системе)? Я всегда нахожу, что тестирование в моей среде является более точным, чем рекомендации от веб-сайтов, поскольку есть несколько факторов, которые могут повлиять на результат, который может быть не указан в вопросе просто из-за незнания того, что эти факторы могут повлиять на результат.

Третье: увеличение размера поля переменной длины является (при условии, что вы не превысите ограничение в 8060 байт) простой операцией метаданных, поскольку никакие фактические данные не изменились бы для такой операции. НО, с другой стороны, уменьшение размера поля переменной длины, даже до чего-то, что будет более чем очевидно работать, не является простым изменением метаданных, потому что SQL Server не знает до сканирования всех строк , что новый запрошенный размер действителен.

Следовательно: Да, это заблокирует таблицу на определенный период времени . Сколько времени? Ну, вот тест, который я только что сделал:

Из какого-то другого тестирования у меня была таблица с одним INT NOT NULLполем и 1 миллионом строк. Я скопировал его в новую таблицу для выполнения этого теста с помощью:

SELECT *, CONVERT(NVARCHAR(MAX), NEWID()) AS [StringField]
INTO dbo.ResizeTest
FROM dbo.ClusteredUnique;

Таким образом, я начинал с похожего сценария с наличием MAXполя (я только что понял, что у вас есть, VARCHARи я использую NVARCHAR, но это не должно изменить поведение, которое я вижу), которое я мог бы затем изменить 500. И в нем есть данные, которые легко помещаются в пределах 500 символов. Это заняло несколько минут.

Я тогда побежал:

ALTER TABLE dbo.ResizeTest ALTER COLUMN [StringField] NVARCHAR(500) NULL;

И это заняло чуть более 11 минут.

Я просто снова запустил тест, на этот раз бросив [ResizeTest]таблицу и изменив оба параметра NVARCHARна простые VARCHAR, просто чтобы быть уверенным, что я сравниваю яблоки с чем-то, что, по крайней мере, похоже на яблоко ;-).

Первоначальное создание таблицы заняло 20 секунд, в то время как ALTER TABLE2 минуты.

Таким образом, с точки зрения оценки времени простоя, это действительно трудно сделать, поскольку оно основано на скоростях дискового ввода-вывода, нужно ли выполнять какие-либо операции автоматического роста файла данных и / или журнала транзакций и т. Д. Вероятно, это большая часть того, почему мой первый тест занял 11 минут, а второй, даже с VARCHARполовиной размера NVARCHARданных, занял всего 2 минуты (т.е. файлы были предварительно выращены в этот момент). Но, тем не менее, вы должны иметь в виду, что мой тест выполняется на моем ноутбуке, который не является самым быстрым диском, но это также всего 1 миллион строк из 2 маленьких столбцов (по 22 байта в строке).

И так как вы спросили, что он будет делать со страницами данных, вот ваш ответ. Я сделал sp_spaceusedпосле создания таблицы, после выполнения ALTER COLUMNи после выполнения ALTER TABLE dbo.ResizeTest REBUILD;. Результаты (следующие цифры основаны на использовании второго теста VARCHAR, а не первого теста NVARCHAR):

After initial table creation:        526,344 KB
After ALTER COLUMN VARCHAR(500):   1,031,688 KB  <--- !! Yikes!!
After ALTER REBUILD:                 526,472 KB

Если вы обеспокоены необходимостью сократить время выполнения операции, ознакомьтесь со статьей, написанной мной о том, как это сделать: реструктурируйте 100-миллионные (или более) таблицы в секундах. SRSLY! (требуется бесплатная регистрация).

Соломон Руцкий
источник
2
Поэтому я скопировал наихудшую таблицу в свой локальный экземпляр (т. Е. На более медленный диск и 1/3 ядра). Я ALTERредактировал каждый столбец подряд - каждое действие занимало меньше секунды. К тому времени, когда они были сделаны, размер таблицы увеличился вдвое, но как только я выполнил REBUILD(что также было операцией в секунду), таблица вернулась к своему первоначальному размеру.
Натейрвин
@nateirvin Это приятно слышать. Вероятно, вы можете ускорить ALTER TABLEоперацию, выполнив все поля за один раз, разделив каждый столбец запятой. Если транзакция слишком велика, разбейте таблицу на 2 оператора ALTER по половине столбцов в каждом. И в зависимости от размера таблицы вы можете даже выполнить REBUILD между каждым из двух операторов ALTER. С чем поиграть. Кроме того, имейте в виду, что операция, вероятно, примет блокировку схемы на время, которое заблокирует весь доступ к таблице.
Соломон Руцки
1
Я сделал каждый ALTERотдельно, чтобы я мог отслеживать изменения размера между каждым, но определенно полезно знать. Благодарность!
nateirvin
1

Из того, что я понял, выполнение инструкции alter не должно занимать много времени, пока за столом не заблокирован другой процесс. Согласно gbn, это просто изменение метаданных: /programming/7261909/is-it-bad-to-use-alter-table-to-resize-a-varchar-column-to-a-larger -размер

Кроме того, что касается того, как они хранятся, кажется, что SQL Server хранит данные varchar на странице 8 КБ, пока не заполнит всю страницу, которая в этот момент заменяет ее указателем и сохраняет как BLOB.

Я предполагаю, что когда вы измените длину, вы не будете обрезать какие-либо записи. Если это так, то в максимуме данные, которые вы конвертируете в varchar (500), должны иметь длину не более 502 байт и не должны иметь указателя.

Короче говоря, мало что должно измениться, если вы не обрезаете какие-либо данные.

DForck42
источник
5
Это абсолютно неверно. Я не буду понижать голос, потому что вы на самом деле проверили это (что больше, чем делают некоторые люди, так что спасибо за это), но вы должны проверить это в масштабе. Ответ, на который вы ссылались, был об увеличении размера, а не уменьшении. Это две совершенно разные операции.
Соломон Руцкий