Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Редки колони в SQL Server:Въздействие върху времето и пространството

SQL Server 2008 въведе редки колони като метод за намаляване на съхранението за нулеви стойности и предоставяне на по-разширяеми схеми. Компромисът е, че има допълнителни разходи, когато съхранявате и извличате стойности, различни от NULL. Заинтересувах се да разбера цената за съхраняване на стойности, различни от NULL, след като разговарях с клиент, който използва този тип данни в промежуточна среда. Те търсят да оптимизират производителността на запис и се чудех дали използването на редки колони има някакъв ефект, тъй като техният метод изискваше вмъкване на ред в таблицата и след това актуализиране. Създадох измислен пример за тази демонстрация, обяснен по-долу, за да определя дали това е добра методология, която те могат да използват.

Вътрешен преглед

Като бърз преглед не забравяйте, че когато създавате колона за таблица, която позволява NULL стойности, ако тя е колона с фиксирана дължина (напр. INT), тя винаги ще използва цялата ширина на колоната на страницата, дори когато колоната е НУЛА. Ако е колона с променлива дължина (напр. VARCHAR), тя ще консумира най-малко два байта в масива за отместване на колони, когато е NULL, освен ако колоните не са след последната попълнена колона (вижте публикацията в блога на Кимбърли Редът на колоните няма значение...по принцип , но – ЗАВИСИ). Рядката колона не изисква никакво пространство на страницата за NULL стойности, независимо дали е колона с фиксирана дължина или с променлива дължина и независимо от това какви други колони са попълнени в таблицата. Компромисът е, че когато се попълни разредена колона, тя отнема четири (4) повече байта място за съхранение, отколкото колона, която не е разредена. Например:

Тип колона Изискване за съхранение
Колона BIGINT, не рядка, с не стойност 8 байта
Колона BIGINT, не рядка, с стойност 8 байта
BIGINT колона, рядка, с не стойност 0 байта
BIGINT колона, рядка, с стойност 12 байта

Ето защо е от съществено значение да се потвърди, че ползата от съхранението надвишава потенциалния удар на производителността от извличането – което може да е незначително въз основа на баланса на четене и запис спрямо данните. Очакваните спестявания на място за различни типове данни са документирани в предоставената по-горе връзка за книги онлайн.

Сценарии за тестване

Зададох четири различни сценария за тестване, описани по-долу, и всяка таблица имаше колона ID (INT), колона Name (VARCHAR(100)) и колона Type (INT), а след това 997 NULLABLE колони.

Идентификатор на теста Описание на таблицата DML операции
1 997 колони от тип данни INT, NULLABLE, неразредени Вмъквайте един ред наведнъж, като попълвате ID, Име, Тип и десет (10) произволни NULLABLE колони
2 997 колони от тип данни INT, NULLABLE, рядко Вмъквайте един ред наведнъж, като попълвате ID, Име, Тип и десет (10) произволни NULLABLE колони
3 997 колони от тип данни INT, NULLABLE, неразредени Вмъквайте един ред наведнъж, като попълвате само ID, Име, Тип, след което актуализирайте реда, добавяйки стойности за десет (10) произволни NULLABLE колони
4 997 колони от тип данни INT, NULLABLE, рядко Вмъквайте един ред наведнъж, като попълвате само ID, Име, Тип, след което актуализирайте реда, добавяйки стойности за десет (10) произволни NULLABLE колони
5 997 колони от тип данни VARCHAR, NULLABLE, неразредени Вмъквайте един ред наведнъж, като попълвате ID, Име, Тип и десет (10) произволни NULLABLE колони
6 997 колони от тип данни VARCHAR, NULLABLE, рядко Вмъквайте един ред наведнъж, като попълвате ID, Име, Тип и десет (10) произволни NULLABLE колони
7 997 колони от тип данни VARCHAR, NULLABLE, неразредени Вмъквайте един ред наведнъж, като попълвате само ID, Име, Тип, след което актуализирайте реда, добавяйки стойности за десет (10) произволни NULLABLE колони
8 997 колони от тип данни VARCHAR, NULLABLE, рядко Вмъквайте един ред наведнъж, като попълвате само ID, Име, Тип, след което актуализирайте реда, добавяйки стойности за десет (10) произволни NULLABLE колони

Всеки тест беше проведен два пъти с набор от данни от 10 милиона реда. Прикачените скриптове могат да се използват за възпроизвеждане на тестване, като стъпките бяха както следва за всеки тест:

  • Създайте нова база данни с предварително оразмерени данни и регистрационни файлове
  • Създайте подходящата таблица
  • Статистика за изчакване на моментна снимка и статистика за файлове
  • Отбележете началния час
  • Изпълнете DML (едно вмъкване или едно вмъкване и една актуализация) за 10 милиона реда
  • Отбележете времето за спиране
  • Статистика за изчакване на моментна снимка и статистически данни за файла и запис в таблица за регистриране в отделна база данни в отделно хранилище
  • Моментна снимка dm_db_index_physical_stats
  • Изхвърлете базата данни

Тестването беше извършено на Dell PowerEdge R720 с 64GB памет и 12GB, разпределени за SQL Server 2014 SP1 CU4 екземпляр. Fusion-IO SSD бяха използвани за съхранение на данни за файловете на базата данни.

Резултати

Резултатите от теста са представени по-долу за всеки тестов сценарий.

Продължителност

Във всички случаи е необходимо по-малко време (средно 11,6 минути) за попълване на таблицата, когато са използвани редки колони, дори когато редът е бил вмъкнат за първи път, след това актуализиран. Когато редът беше вмъкнат за първи път и след това актуализиран, тестът отне почти два пъти повече време за изпълнение в сравнение с момента, когато редът беше вмъкнат, тъй като бяха изпълнени два пъти повече модификации на данни.

Средна продължителност за всеки тестов сценарий

Изчакайте статистика
Идент. № на теста Среден процент Средно изчакване (секунди)
1 16.47 0,0001
2 14.00 0,0001
3 16,65 0,0001
4 15.07 0,0001
5 12,80 0,0001
6 13,99 0,0001
7 14,85 0,0001
8 15.02 0,0001

Статистиката за чакане беше последователна за всички тестове и не могат да се направят заключения въз основа на тези данни. Хардуерът отговаряше в достатъчна степен на изискванията за ресурси във всички тестови случаи.

Файлова статистика

Средно IO (четене и запис) на файл с база данни

Във всички случаи тестовете с разредени колони генерираха по-малко IO (особено записвания) в сравнение с колоните, които не са разредени.

Индексни физически статистически данни
Тестов случай Брой редове Общ брой страници (клъстериран индекс) Общо пространство (GB) Средно пространство, използвано за листни страници в CI (%) Среден размер на записа (байтове)
1 10 000 000 10 037 312 76 51,70 4 184,49
2 10 000 000 301 429 2 98,51 237,50
3 10 000 000 10 037 312 76 51,70 4 184,50
4 10 000 000 460 960 3 64.41 237,50
5 10 000 000 1 823 083 13 90,31 1326,08
6 10 000 000 324 162 2 98,40 255.28
7 10 000 000 3 161 224 24 52.09 1326,39
8 10 000 000 503 592 3 63.33 255.28

Съществуват значителни разлики в използването на пространството между неразредените и разредените таблици. Това е най-забележимо, когато се разглеждат тестови случаи 1 и 3, където е използван тип данни с фиксирана дължина (INT), в сравнение с тестови случаи 5 и 7, където е използван тип данни с променлива дължина (VARCHAR(255)). Целочислените колони консумират дисково пространство дори когато са NULL. Колоните с променлива дължина заемат по-малко дисково пространство, тъй като само два байта се използват в офсетния масив за NULL колони и никакви байтове за тези NULL колони, които са след последната попълнена колона в реда.

Освен това процесът на вмъкване на ред и след това актуализирането му причинява фрагментация за теста с колона с променлива дължина (случай 7), в сравнение с простото вмъкване на реда (случай 5). Размерът на таблицата почти се удвоява, когато вмъкването е последвано от актуализацията, поради разделянето на страниците, което възниква при актуализиране на редовете, което оставя страниците наполовина пълни (срещу 90% пълни).

Резюме

В заключение виждаме значително намаляване на дисковото пространство и IO, когато се използват редки колони и те се представят малко по-добре от нередките колони в нашите прости тестове за модификация на данни (обърнете внимание, че производителността на извличане също трябва да се има предвид; може би предмет на друг пост).

Редките колони имат много специфичен сценарий на използване и е важно да се проучи количеството спестено дисково пространство въз основа на типа данни за колоната и броя на колоните, които обикновено ще се попълват в таблицата. В нашия пример имахме 997 редки колони и попълнихме само 10 от тях. Най-много в случай, че използвания тип данни е цяло число, ред на ниво лист на клъстерирания индекс ще консумира 188 байта (4 байта за идентификатора, 100 байта максимум за името, 4 байта за типа и след това 80 байта за 10 колони). Когато 997 колони не са били разредени, тогава за всяка колона са били разпределени 4 байта, дори когато е NULL, така че всеки ред е бил поне 4000 байта на ниво лист. В нашия сценарий редките колони са абсолютно приемливи. Но ако попълним 500 или повече редки колони със стойности за колона INT, тогава спестяването на място се губи и производителността на модификацията може вече да не е по-добра.

В зависимост от типа данни за вашите колони и очаквания брой колони, които трябва да бъдат попълнени от общия брой, може да искате да извършите подобно тестване, за да се уверите, че когато използвате редки колони, производителността и съхранението на вмъкване са сравними или по-добри, отколкото при използване на не -редки колони. За случаите, когато не всички колони са попълнени, редките колони определено си струва да се обмислят.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server 2005 Пивот върху неизвестен брой колони

  2. SQL Server използва висок процесор при търсене в nvarchar низове

  3. INSERT INTO срещу SELECT INTO

  4. Вземете списък на поддържаните часови зони в SQL Server (T-SQL)

  5. Грешка на SQL Server - HRESULT E_FAIL е върнат от повикване към COM компонент