Производительность при создании суррогатных ключей с помощью идентификаторов и последовательностей может зависеть от нескольких факторов, в том числе от того, созданы значения в tempdb или пользовательской базе данных, от того, какой из двух элементов используется, и от значения кэша. Я выполнил тест производительности, чтобы определить влияние различных факторов и сравнить последовательность с идентификатором. Для подготовки среды к тестированию был использован программный код, приведенный в листинге 1.
В процессе подготовки создаются пользовательская база данных с именем testdb. вспомогательная функция с именем GetNums, которая возвращает последовательность целых чисел в запрошенном диапазоне, и последовательности как в пользовательской базе данных, так и в tempdb.
Затем я воспользовался программным кодом листинга 2, чтобы выполнить собственно тест производительности.
Программный код измеряет производительность при заполнении таблицы с 10000000 строк, без последовательности или идентификатора, с последовательностью, с идентификатором, как в пользовательской базе данных, гак и в tempdb, с различными значениями кэша. Определяется объем операций с журналом (число записей и обший размер) путем обращения к функции fndbk^o и после вставки. Измерения и вставка выполняются в одной транзакции, чтобы избежать саморециркуляции журнала. Программный код также определяет число очисток журнала, вызванных вставками, запрашивая счетчик производительности Log Flushes/sec из представления sys.dm_ os_performance_counters. Хотя, судя по имени счетчика, он показывает число очисток в секунду, в действительности это просто общее число очисток, выполненных на данный момент. На рисунке 2 показаны результаты теста производительности на моем компьютере.
Большинство столбцов не нуждаются в дополнительных пояснениях. Столбец normduration содержит длительность в миллисекундах за вычетом длительности вставки без формирования значений последовательности или идентификатора. Эта мера дает представление о времени, которое необходимо для создания 10000000 значений последователь
ности или идентификатора без учета времени собственно вставки. Обратите внимание на несколько очень интересных особенностей. Производительность идентификатора и последовательности в tempdb весьма похожа при использовании одинаковых значений кэша. Кроме того, в tempdb производительность гораздо лучше, чем в пользовательской базе данных, особенно при малых значениях кэша. Дело в том, что в tempdb не нужно вносить в журнал относящиеся к кэшу операции записи на диск, поскольку после перезапуска ничего восстанавливать не нужно. В пользовательской базе данных необходимо делать запись в журнал для каждой относящейся к кэшу операции записи на диск. Имеется любопытное различие в производительности между последовательностью и идентификатором в пользовательской базе данных при отсутствии кэша и при малых его значениях. Например, без кэша требуется менее двух минут для формирования 10000000 значений идентификатора, но почти час для создания такого же числа значений последовательности. И это несмотря на то, что объем записей в журнал одинаков. Причина такого различия должна быть связана со способом очистки буфера журнала в двух случаях. Если при использовании идентификатора происходит сбой, то проблем после восстановления не возникает, если повторно используется значение, которое было вставлено, но не зафиксировано. Поэтому нет причин очищать буфер журнала после связанной с кэшем операции записи. Буфер журнала очищается после заполнения.
При использовании последовательности ситуация иная. Клиентское приложение может запросить новое значение последовательности и уже использовать его, даже если транзакция не зафиксирована. Если происходит сбой, не существует способа запросить новое значение последовательности от клиента. Поэтому SQL Server очищает буфер журнала после каждой операции записи на диск, связанной с кэшем. При использовании последовательности без кэша в пользовательской базе данных (см. рисунок 2) производится столько же (или больше) очисток журнала, сколько создано значений последовательности, тогда как идентификатор без кэша приносит гораздо меньше очисток.
Комментарии