SQL Server кэширует и значения для IDENTITY


sql-server-kjeshiruet-i-znachenija-dlja-identity_1.png

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

Как отмечалось, в случае с последовательностями, если работа системы завершается непредвиденно, вы теряете оставшиеся кэшированные значения в текущем блоке и просто имеете пробел в значениях. В случае с IDENTITY после перезапуска SQL Server во время восстановления выполняется просмотр записей журнала, чтобы определить последнее использованное значение IDENTITY Таким образом, оставшиеся кэшированные значения не теряются (кроме особых случаев, маловероятных из-за небольшого временного окна).

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

Рассмотрим некоторые показатели производительности, полученные в ходе тестирования на моем ноутбуке. Это не исчерпывающий тест, а довольно простая проверка, дающая общее представление о производительности. Воспользуйтесь исходным текстом листинга, чтобы создать объекты, используемые в этом тесте производительности.

Программный код в листинге создает вспомогательную функцию с именем GetNums, которая возвращает последовательность целых чисел запрошенного размера. Также формируется таблица ТІ со свойством IDENTITY, последовательность Seql и таблица Т2 с выражением по умолчанию, получающим значение из Seql.

Сначала я проверил, как много времени требуется для заполнения таблицы Т2 1 000000 строк без создания значений последовательности или IDENTITY, с помощью следующего программного кода:

TRUNCATE TABLE dbo.T2;

INSERT INTO dbo.T2(col1, col2)

SELECT n, 0x42

FROM dbo.GetNums(1000000);

Этот фрагмент кода был выполнен на моем ноутбуке за 7 секунд. Код выполнялся более одного раза в каждом тесте, чтобы в случае, если потребуется увеличение tempdb, этого не произошло в процессе измерений производительности.

Для определения производительности IDENTITY использовался следующий программный код:

TRUNCATE TABLE dbo.TI;

INSERT INTO dbo.TI(col2)

SELECT 0x42

FROM dbo.GetNums(1000000); Выполнение данного фрагмента кода заняло 9 секунд. Таким образом, примерно 2 секунды занимает создание значений IDENTITY. Напомним, что во время подготовки данной статьи в SQL Server для IDENTITY использовалось жестко заданное значение 10; изменить его нельзя.

Затем я задействовал следующий программный код для тестирования производительности объекта последовательности с параметрами кэширования по умолчанию (CACHE 50):

TRUNCATE TABLE dbo 12;

INSERT INTO dbo.T2(col2)

SELECT 0x42

FROM dbo.GetNums(IOOOOOO); Выполнение этого фрагмента кода заняло 8 секунд. Как мы видим, производительность последовательности с параметрами кэширования по умолчанию выше, чем у IDENTITY, что можно объяснить увеличением значения кэша. Наконец, я использовал следующий программный код для тестирования производительности последовательности без кэширования:

ALTER SEQUENCE dbo.Seql N0 CACHE;

TRUNCATE TABLE dbo.T2;

INSERT INTO dbo.T2(col2)

SELECT 0x42

FROM dbo.GetNums(1000000);

Комментарии