Изменить: я только что заметил, что есть статья базы знаний ИСПРАВЛЕНИЕ: запрос, использующий функцию DECRYPTBYKEY занимает много времени в SQL Server 2014, но он у меня установлен, и, похоже, это не меняет первоначальных выводов, приведенных ниже.
Выполнение следующего кода в SQL Server 2012 (11.0.5343.0) и 2014 (окончательная первоначальная версия) на четырехъядерном (Intel Core i5-2320) настольном компьютере X64 под управлением Windows 10.
OPEN SYMMETRIC KEY MySymmetricKeyName DECRYPTION BY CERTIFICATE MyCertificateName;
DECLARE @B VARBINARY(100);
WITH t
AS (SELECT ROW_NUMBER() OVER (ORDER BY @@SPID) AS article_id
FROM sys.all_objects o1,
sys.all_objects o2,
sys.all_objects o3,
sys.all_objects o4)
SELECT @B = ENCRYPTBYKEY(KEY_GUID('MySymmetricKeyName'), CONVERT(VARBINARY(100), article_id))
FROM t
И глядя на это в Process Explorer
2012
![введите здесь описание изображения](https://i.stack.imgur.com/7AKYP.png)
2014
![введите здесь описание изображения](https://i.stack.imgur.com/MtHCo.png)
Сразу становятся очевидными две вещи.
Версия 2012 года использует меньше ЦП и максимально использует одно ядро. Версия 2014 года использует более одного ядра и значительно активнее работает в режиме ядра (красный).
Окно потоков Process Explorer показывает
2012
![введите здесь описание изображения](https://i.stack.imgur.com/lZrM1.png)
Один поток монополизирует планировщик.
2014
![введите здесь описание изображения](https://i.stack.imgur.com/lo7Yz.png)
Здесь работа выполняется двумя потоками (поток 3212 выполняет задачу бездействия sqldk.dll!SOS_Scheduler::Idle
).
Отслеживание процесса 2014 года показывает, что SQL Server и эти два потока сталкиваются с большим количеством переключений контекста (трассировка сделана в другое время, чем на предыдущем снимке экрана, поэтому идентификаторы потоков различаются)
![введите здесь описание изображения](https://i.stack.imgur.com/dBBvq.png)
Отслеживание двух процессов с помощью Windows Performance Toolkit показывает некоторые существенные различия во времени, затраченном на разные модули.
2012
![введите здесь описание изображения](https://i.stack.imgur.com/tbSD5.png)
2014
![введите здесь описание изображения](https://i.stack.imgur.com/F1RIx.png)
На данный момент я не уверен, почему версия 2014 сообщает о 25% ЦП в этом представлении по сравнению с 30% в других, но в любом случае очевидно, что время, затрачиваемое на ntoskrnl.exe, резко увеличилось между версиями, и теперь тратится 60% времени. в коде в этом модуле. Время, затрачиваемое на шифрование, конечно, соответственно сократилось.
При подключении профилировщика кода VS версия 2012 года выглядит как этот, а версия 2014 – как это.
Таким образом, похоже, что в 2014 году есть дополнительная логика, чтобы остановить перегрузку планировщика, и он отключается чаще, как показано дополнительными элементами ниже.
![введите здесь описание изображения](https://i.stack.imgur.com/eQ42Z.png)
(по сравнению с 2012 г.)
![введите здесь описание изображения](https://i.stack.imgur.com/Vu7F1.png)
Попытка в обеих версиях выполнить операцию 1 миллион раз...
SET STATISTICS TIME ON;
DECLARE @B VARBINARY(100);
OPEN SYMMETRIC KEY MySymmetricKeyName DECRYPTION BY CERTIFICATE MyCertificateName;
DBCC SQLPERF("sys.dm_os_wait_stats", CLEAR);
WITH t
AS (SELECT ROW_NUMBER() OVER (ORDER BY @@SPID) AS article_id
FROM master..spt_values v1,
master..spt_values v2
WHERE v1.type = 'P'
AND v2.type = 'P'
AND v1.number BETWEEN 1 AND 1000
AND v2.number BETWEEN 1 AND 1000)
SELECT @B = ENCRYPTBYKEY(KEY_GUID('MySymmetricKeyName'), CONVERT(VARBINARY(100), article_id))
FROM t
SELECT *
FROM sys.dm_os_wait_stats
WHERE wait_type IN ( 'PREEMPTIVE_OS_CRYPTOPS', 'SOS_SCHEDULER_YIELD' );
2012 (время процессора = 2344 мс, прошедшее время = 2383 мс.)
![введите здесь описание изображения](https://i.stack.imgur.com/NLYt5.png)
Хорошо видно, что хотя тип ожидания PREEMPTIVE_OS_CRYPTOPS
существует в 2012 году, в данном случае он не используется.
Вместо этого выглядит так, как будто запрос более или менее монополизирует планировщик (хотя все еще добровольно уступает в конце своего кванта 4 мс - 4 * 597 = 2388)
2014 (время процессора = 8188 мс, прошедшее время = 10569 мс.)
![введите здесь описание изображения](https://i.stack.imgur.com/GnR1l.png)
Принимая во внимание, что в 2014 году каждый вызов функции ENCRYPTBYKEY
сталкивается с этим типом ожидания, и в этом случае он (в сочетании с переключением контекста) добавил 8,2 секунды к общему истекшему времени.
Стеки вызовов для некоторых наиболее трудоемких вызовов ядра выделены ниже.
![введите здесь описание изображения](https://i.stack.imgur.com/RuJtJ.png)
Я также попробовал еще один эксперимент
2014 — SQL Server привязан к одному ЦП
(время ЦП = 4500 мс, прошедшее время = 6648 мс.)
![введите здесь описание изображения](https://i.stack.imgur.com/cAxKm.png)
Время здесь находилось где-то между производительностью 2012 года и производительностью без аффинитиза 2014 года, когда код выполнялся на нескольких разных ядрах.
person
Martin Smith
schedule
17.03.2015