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

Нови промени в колони само за метаданни в SQL Server 2016

ALTER TABLE ... ALTER COLUMN командата е много мощна. Можете да го използвате, за да промените типа данни на колоната, дължината, точността, мащаба, нулирането, съпоставянето... и много други неща освен това.

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

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

В зависимост от вида на промяната и конфигурацията на базата данни, ALTER COLUMN командата ще трябва да извърши едно от следните действия:

  1. Променете метаданните само в системните таблици.
  2. Проверете всички съществуващи данни за съвместимост, след което променете метаданните.
  3. Пренапишете някои или всички съхранени данни, за да съответстват на новата дефиниция.

Вариант 1 представлява идеалния случай от гледна точка на производителността. Изисква само няколко промени в системните таблици и минимално количество регистриране. Операцията все пак ще изисква ограничителна модификация на схемата Sch-M заключете, но самите промени в метаданните ще завършат много бързо, независимо от размера на таблицата.

Промени само за метаданни

Има редица специални случаи, за които трябва да внимавате, но като общо обобщение, следните действия изискват промени само в метаданните:

  • Преминаване от NOT NULL до NULL за същия тип данни.
  • Увеличаване на максималния размер на varchar , nvarchar , или varbinary колона (с изключение на max ).

Подобрения в SQL Server 2016

Темата на тази публикация са допълнителните промени, които са разрешени само за метаданни от SQL Server 2016 нататък . Не са необходими промени в синтаксиса и не е необходимо да се променят настройките за конфигурация. Получавате тези недокументирани подобрения безплатно.

Новите възможности са насочени към подмножество от фиксирана дължина типове данни. Новите способности се прилагат към таблици за съхранение на редове при следните обстоятелства:

  • Компресията трябва да е активирана:
    • На всички индекси и дялове , включително базовата купчина или клъстериран индекс.
    • Или ROW или PAGE компресия.
    • Индексите и дяловете може да използват смес от тези нива на компресия. Важното е, че няма некомпресирани индекси или дялове.
  • Промяна от NULL до NOT NULL ене е позволено .
  • Следните промени в типа на цяло число се поддържат:
    • smallint към integer или bigint .
    • integer към bigint .
    • smallmoney към money (използва вътрешночислено представяне).
  • Следните низови и двоични промени в типа се поддържат:
    • char(n) към char(m) или varchar(m)
    • nchar(n) към nchar(m) или nvarchar(m)
    • binary(n) към binary(m) или varbinary(m)
    • Всичко по-горе само за n < m и m != max
    • Промени в съпоставянето не са разрешени

Тези промени могат да бъдат само с метаданни, тъй като основното оформление на двоични данни не се променя, когато Дескриптор на колона използва се формат на ред (оттук и необходимостта от компресиране). Без компресия магазинът на редове използва оригиналния FixedVar представяне, което не може да побере тези промени на типа данни с фиксирана дължина, без да се пренапише физическото оформление.

Може да забележите, че tinyint е пропуснат от списъка с целочислени типове. Това е така, защото е без знак, докато всички други типове цели числа са със знак, така че промяна само на метаданни не е възможна. Например, стойност от 255 може да се побере в един байт за tinyint , но изисква два байта във всеки от подписаните формати. Подписаните формати могат да задържат от -128 до +127 в един байт, когато са компресирани.

Пример за цяло число

Едно много удобно приложение на това подобрение е промяна на типа данни на колона с IDENTITY собственост.

Да кажем, че имаме следната таблица на купчина, използвайки компресия на редове (компресията на страница също би работила):

ИЗПУСКАНЕ НА ТАБЛИЦА, АКО СЪЩЕСТВУВА dbo.Test;GOCREATE TABLE dbo.Test( id integer IDENTITY NOT NULL, some_value integer NOT NULL)WITH (DATA_COMPRESSION =ROW);

Нека добавим 5 милиона реда данни. Това ще бъде достатъчно, за да стане очевидно (от гледна точка на производителността) дали промяната на типа данни на колоната е операция само с метаданни или не:

С Числа КАТО( ИЗБЕРЕТЕ n =ROW_NUMBER() НАД (ПОРЪЧКА ОТ @@SPID) ОТ sys.all_columns КАТО AC1 КРЪСТО ПРИСЪЕДИНЕТЕ sys.all_columns КАТО AC2 ПОРЪЧАЙТЕ ПО n ОТМЕСТВАНЕ 0 РЕДОВЕ ИЗВЛЕЧВАНЕ ПЪРВО 5 * 1000 * R INSERT dbo.Test WITH (TABLOCKX)( some_value)SELECT N.nFROM Numbers AS N;

След това ще зададем повторно IDENTITY за да изглежда, че сме почти в точката на изчерпване на стойности, които ще се поберат в integer :

DBCC CHECKIDENT( N'dbo.Test', RESEED, 2147483646);

Можем успешно да добавим още един ред:

INSERT dbo.Test (some_value)VALUES (123456);

Но опит за добавяне на още един ред:

INSERT dbo.Test (some_value)VALUES (7890);

Резултатът е съобщение за грешка:

Съобщение 8115, ниво 16, състояние 1, ред 1
Грешка при аритметично препълване при преобразуване на IDENTITY в тип данни int.

Можем да поправим това, като преобразуваме колоната в bigint :

ALTER TABLE dbo.TestALTER COLUMN id bigint NOT NULL;

Благодарение на подобренията в SQL Server 2016, тази команда променя само метаданни , и завършва незабавно. Предишният INSERT операторът (този, който е довел грешката при аритметичното препълване) сега завършва успешно.

Тази нова способност не решава всички проблеми около промяната на типа на колона с IDENTITY Имот. Все пак ще трябва да пускаме и пресъздаваме всички индекси в колоната, да пресъздаваме всички рефериращи външни ключове и т.н. Това е малко извън обхвата на тази публикация (въпреки че Аарон Бертран е писал за това и преди). Възможността да промените типа като операция само с метаданни със сигурност не боли. С внимателно планиране другите необходими стъпки могат да бъдат направени възможно най-ефективни, например като се използва минимално регистриран или ONLINE операции.

Бъдете внимателни със синтаксиса

Уверете се, че винагите посочете NULL или NOT NULL при промяна на типове данни с ALTER COLUMN . Да кажем например, че искаме също да променим типа данни на some_value колона в нашата тестова таблица от integer NOT NULL към bigint NOT NULL .

Когато пишем командата, пропускаме NULL или NOT NULL квалификатор:

ALTER TABLE dbo.TestALTER COLUMN some_value bigint;

Тази команда завършва успешно като промяна само на метаданни, но също така премахва NOT NULL ограничение. Колоната вече е bigint NULL , което не е това, което възнамерявахме. Това поведение е документирано, но е лесно да се пренебрегне.

Може да се опитаме да поправим грешката си с:

ALTER TABLE dbo.TestALTER COLUMN some_value bigint NOT NULL;

Това ене промяна само на метаданни. Не ни е позволено да променяме от NULL до NOT NULL (вижте по-ранната таблица, ако имате нужда от освежаване на условията). SQL Server ще трябва да провери всички съществуващи стойности, за да се увери, че няма нулеви стойности. След това физически пренаписва всеки ред на масата. Освен че са бавни сами по себе си, тези действия генерират голяма част от регистрационните файлове на транзакциите, които могат да имат въздействащ ефект.

Като странична забележка, същата грешка не е възможна за колони с IDENTITY Имот. Ако напишем ALTER COLUMN израз без NULL или NOT NULL в този случай машината услужливо приема, че имаме предвид NOT NULL тъй като свойството identity не е разрешено в колони с нула. Все пак е страхотна идея да не разчитате на това поведение.

Винаги посочвайте NULL или NOT NULL с ALTER COLUMN .

Сравняване

Необходима е особено внимание, когато се променя колона с низове, която има съпоставяне, което не съответства на стандартното за базата данни.

Например, да речем, че имаме таблица със съпоставяне, чувствително към малки и големи букви (да приемем, че базата данни по подразбиране е различна):

ИЗПУСКАНЕ НА ТАБЛИЦАТА, АКО СЪЩЕСТВУВА dbo.Test2;GOCREATE TABLE dbo.Test2( id integer IDENTITY NOT NULL, some_string char(8) СЪБОРЯВАНЕ Latin1_General_100_CS_AS НЕ NULL)С (DATA_COMPRESSION> =ROW); 

Добавете 5 милиона реда данни:

С Числа КАТО( ИЗБЕРЕТЕ n =ROW_NUMBER() НАД (ПОРЪЧКА ОТ @@SPID) ОТ sys.all_columns КАТО AC1 КРЪСТО ПРИСЪЕДИНЕТЕ sys.all_columns КАТО AC2 ПОРЪЧАЙТЕ ПО n ОТМЕСТВАНЕ 0 РЕДОВЕ ИЗВЛЕЧВАНЕ ПЪРВО 5 * 1000 * R INSERT dbo.Test2 WITH (TABLOCKX)( some_string)SELECT CONVERT(char(8), N.n) COLLATE Latin1_General_100_CS_ASFROM Числа AS N;

Удвоете дължината на колоната на низа, като използвате следната команда:

ALTER TABLE dbo.Test2ALTER COLUMN some_string char(16) NOT NULL;

Не забравяйте да посочим NOT NULL , но забравих за сравнението по подразбиране. SQL Server предполага, че сме искали да променим съпоставянето на базата данни по подразбиране (Latin1_General_CI_AS за моята тестова база данни). Промяната на съпоставянето не позволява на операцията да бъде само с метаданни и така операцията работи за няколко минути, генерирайки купища регистрационни файлове.

Създайте отново таблицата и данните с помощта на предишния скрипт, след което опитайте ALTER COLUMN команда отново, но посочване на съществуващото съпоставяне, което не е по подразбиране като част от командата:

ALTER TABLE dbo.Test2ALTER COLUMN some_string char(16) COLLATE Latin1_General_100_CS_AS NOT NULL;

Промяната сега завършва незабавно, като операция само с метаданни. Както при NULL и NOT NULL синтаксис, струва си да бъдете изрични, за да избегнете инциденти. Това е добър съвет като цяло, не само за ALTER COLUMN .

Компресия

Моля, имайте предвид, че компресията трябва да бъде изрично посочена за всеки индекс и отделно за основната таблица, ако е купчина. Това е друг пример, при който използването на съкратен синтаксис или преки пътища може да предотврати желания резултат.

Например, следната таблица не посочва изрично компресиране нито за първичния ключ, нито за дефиницията на вграден индекс:

СЪЗДАДЕТЕ ТАБЛИЦА dbo.Test( id integer IDENTITY NOT NULL PRIMARY KEY, some_value integer NOT NULL INDEX [IX dbo.Test some_value])WITH (DATA_COMPRESSION =PAGE);

PRIMARY KEY ще има присвоено име, по подразбиране CLUSTERED ,и да бъде PAGE компресиран. Вграденият индекс ще бъде NONCLUSTERED и изобщо не е компресиран. Тази таблица няма да бъде активирана за нито една от новите оптимизации, тъй като не всички индекси и дялове са компресирани.

Много по-добра и по-ясна дефиниция на таблицата би била:

СЪЗДАДЕТЕ ТАБЛИЦА dbo.Test( id integer IDENTITY NOT NULL ОГРАНИЧЕНИЕ [PK dbo.Test id] ПЪРВИЧЕН КЛУСТ, КЛУСТРИРАН С (DATA_COMPRESSION =PAGE), some_value integer НЕ НУЛ ИНДЕКС [IX dbo.Test some_value] R. ) );

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

Има различни начини да напишете тази CREATE TABLE изявление по изричен начин, така че има елемент на лично предпочитание. Важният момент е винаги да бъдете изрични за това, което искате. Това се отнася за отделен CREATE INDEX също и изявления.

Разширени събития и флаг за проследяване

Има разширено събитие специално за новите метаданни ALTER COLUMN операции, поддържани в SQL Server 2016 нататък.

Разширеното събитие е compressed_alter_column_is_md_only в Отстраняване на грешки канал. Неговите полета за събития са object_id , column_id и is_md_only (вярно/невярно).

Това събитие показва само дали дадена операция е само с метаданни поради новите възможности на SQL Server 2016. Промените в колоните, които са били само с метаданни преди 2016 г., ще покажат is_md_only = false въпреки че все още е само с метаданни.

Други разширени събития, полезни за проследяване на ALTER COLUMN операциите включват metadata_ddl_alter_column и alter_column_event , и двете в Analytic канал.

Ако трябва да деактивирате новите възможности на SQL Server 2016 по някаква причина може да се използва недокументиран глобален (или стартиращ) флаг за проследяване 3618. Този флаг за проследяване не е ефективен, когато се използва на ниво сесия. Няма начин да посочите флаг за проследяване на ниво заявка с ALTER COLUMN команда.

Последни мисли

Възможността да промените някои типове данни с фиксирана дължина с цели данни с промяна само на метаданни е много добре дошло подобрение на продукта. Това изисква таблицата вече да е напълно компресирана, но това така или иначе става все по-често срещано нещо. Това е особено вярно, тъй като компресирането беше активирано във всички издания, започвайки със SQL Server 2016 Service Pack 1.

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

Не всичко е добра новина с активирана компресия. Споменах по-рано, че SQL Server понякога може да извърши промяна само на метаданни, след като провери дали всички съществуващи стойности ще се преобразуват успешно в новия тип. Такъв е случаят, когато използвате ALTER COLUMN за промяна от integer към smallint например. За съжаление, тези операции в момента не са само за метаданни за компресирани обекти.

Потвърждения

Специални благодарности на Панайотис Антонопулос (главен софтуерен инженер) и Мирек Щайно (старши програмен мениджър) от продуктовия екип на SQL Server за тяхната помощ и насоки по време на проучването и писането на тази статия.

Нито една от подробностите, дадени в тази работа, не трябва да се разглежда като официална документация на Microsoft или изявления за продукти.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изчислете броя на записите за всяка дата между 2 дати

  2. Изчислете общата цена на притежание за мониторинг на SQL Server

  3. Как да свържа sql сървър с php с помощта на xampp?

  4. SSMS версия 18 – няма диаграми на база данни

  5. SELECT DISTINCT игнорира различни случаи