Який ефект призведе до зменшення розміру стовпчика varchar на файл бази даних?


15

У нашій базі даних є ряд таблиць, у яких є VARCHAR(MAX)стовпці, де VARCHAR(500)(або щось набагато менше max) буде достатньо. Я, природно, хочу їх очистити та зменшити розміри до більш розумних рівнів. "Як" це зробити, я розумію: моє запитання полягає в тому, що зміна цих стовпців буде робити із сторінками та постійними компонентами на диску? (Там багато інформації про те, що відбувається під час вирощування стовпця, але виникають проблеми з пошуку інформації про те, що відбувається, коли ви стискаєте його.)

Деякі таблиці мають дуже малу кількість рядків, тому я не переживаю за вартість змін, але деякі досить великі, і я переживаю за те, щоб вони могли бути реорганізовані та спричинити багато блокувань / простоїв. На практиці я просто хочу спосіб оцінити вікно обслуговування. Загалом, я хотів би краще зрозуміти, як поводиться двигун бази даних у цьому випадку.

Спасибі заздалегідь!

Редагувати:

У мене є 20 таблиць, на які я дивлюся, хоча лише у половини їх кількість рядків перевищує 1000. Найбільший - майже мільйон рядів. Найгіршим правопорушником є ​​таблиця з 350 000 рядків і чотирма VARCHAR(MAX)стовпцями, які можуть скоротитися до VARCHAR(500)рівня.

Відповіді:


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]стіл і змінивши обидва NVARCHARs на справедливі VARCHAR, просто щоб бути впевненим, що я порівнюю яблука з чимось, що принаймні схоже на яблуко ;-).

Початкове створення таблиці зайняло 20 секунд, а ALTER TABLEзаняття - 2 хвилини.

Отже, з точки зору оцінки простоїв, це дуже важко зробити, оскільки це базується на швидкості введення / виводу диска, незалежно від того, чи потрібно проводити будь-які операції автоматичного зростання в файлі даних та / або в журналі транзакцій тощо. це, мабуть, значна частина, чому мій перший тест потребував 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

@nateirvin Це добре чути. Ви, ймовірно, можете прискорити ALTER TABLEоперацію, виконавши всі поля одним пострілом, розділяючи кожну колонку комою. Якщо транзакція занадто велика, то розділіть таблицю на 2 ALTER заяви на половину стовпців кожен. І залежно від того, наскільки велика таблиця набуває, ви навіть можете робити ПОВТОРЕННЯ між кожним з двох операторів 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 зберігав варчарські дані на 8k сторінці, поки не заповнив цілу сторінку, яка в цей момент замінює її вказівником і зберігає її як BLOB.

Я припускаю, що змінивши довжину, ви не будете обрізати жодні записи. Якщо так, то максимум дані, які ви перетворюєте на varchar (500), повинні становити не більше 502 байт і не повинні мати вказівника.

Отже, якщо коротко розповісти, не багато чого слід змінити, доки ви не обріжете жодних даних.


5
Це абсолютно неправильно. Я не підкажу, бо ви насправді перевірили це (що більше, ніж деякі люди, тому дякую за це), але вам потрібно перевірити це в масштабі. Відповідь, з якою ви пов’язували, стосувалася збільшення розміру, а не зменшення. Це дві дуже різні операції.
Соломон Руцький
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.