Сценарий: SQL Server 2014 (v12.0.4100.1)
.NET Service выполняет этот запрос:
SELECT name, base_object_name
FROM sys.synonyms
WHERE schema_id IN (SELECT schema_id
FROM sys.schemas
WHERE name = N'XXXX')
ORDER BY name
... который возвращает около 6500 строк, но часто истекает через 3 + минуты. XXXX
Выше не "ДБО.
Если я выполню этот запрос в SSMS как UserA, запрос вернется менее чем за секунду.
При запуске от имени пользователя B (именно так подключается служба .NET), запрос занимает 3–6 минут и все время занимает% ЦП, равный 25% (из 4 ядер).
UserA - это доменное имя в роли sysadmin.
UserB - это логин SQL с:
EXEC sp_addrolemember N'db_datareader', N'UserB'
EXEC sp_addrolemember N'db_datawriter', N'UserB'
EXEC sp_addrolemember N'db_ddladmin', N'UserB'
GRANT EXECUTE TO [UserB]
GRANT CREATE SCHEMA TO [UserB]
GRANT VIEW DEFINITION TO [UserB]
Я могу продублировать это в SSMS, обернув вышеприведенный SQL в Execute as...Revert
блок, так что код .NET будет за кадром.
План выполнения выглядит так же. Я проанализировал XML и есть только незначительные различия (CompileTime, CompileCPU, CompileMemory).
IO Stats все показывают отсутствие физических чтений:
Таблица «sysobjvalues». Сканирование счетчик 0, логическое чтение 19970, физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0. Таблица «Рабочий файл». Сканирование счетчик 0, логическое чтение 0, физическое чтение 0, чтение с опережением 0, логическое чтение с бита 0, физическое чтение с бита 0, чтение с опережением чтения 0. Стол «Рабочий стол». Сканирование счетчик 0, логическое чтение 0, физическое чтение 0, чтение с опережением 0, логическое чтение с бита 0, физическое чтение с бита 0, чтение с опережением чтения 0. Таблица 'sysschobjs'. Сканирование 1, логическое чтение 9122, физическое чтение 0, чтение с опережением 0, логическое чтение 1, физическое чтение 1, чтение с опережением 0. Таблица 'sysclsobjs'. Сканирование счетчик 0, логическое чтение 2, физическое чтение 0, чтение с опережением 0, логическое чтение с бита 0, физическое чтение с бита 0, чтение с опережением чтения 0.
Состояние ожидания XEvent (для запроса ~ 3 минуты):
+ --------------------- + ------------ + -------------- -------- + ------------------------------ + ---------- ------------------- + | Тип ожидания | Подождите, граф | Общее время ожидания (мс) | Общее время ожидания ресурса (мс) | Общее время ожидания сигнала (мс) | + --------------------- + ------------ + -------------- -------- + ------------------------------- + --------- -------------------- + | SOS_SCHEDULER_YIELD | 37300 | 427 | 20 | 407 | | NETWORK_IO | 5 | 26 | 26 | 0 | | IO_COMPLETION | 3 | 1 | 1 | 0 | + --------------------- + ------------ + -------------- -------- + ------------------------------- + --------- -------------------- +
Если я переписываю запрос (в SSMS у меня нет доступа к коду приложения),
declare @id int
SELECT @id=schema_id FROM sys.schemas WHERE name = N'XXXX'
SELECT a.name, base_object_name FROM sys.synonyms a
WHERE schema_id = @id
ORDER BY name
затем UserB работает с той же (быстрой) скоростью, что и UserA.
Если я добавлю db_owner
в UserB, то снова запрос будет <1 сек.
Схема, созданная с помощью этого шаблона:
DECLARE @TranName VARCHAR(20)
SELECT @TranName = 'MyTransaction'
BEGIN TRANSACTION @TranName
GO
IF NOT EXISTS (SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = '{1}')
BEGIN
EXEC('CREATE SCHEMA [{1}]')
EXEC sp_addextendedproperty @name='User', @value='{0}', @level0type=N'Schema', @level0name=N'{1}'
END
GO
{2}
COMMIT TRANSACTION MyTransaction;
GO
И {2}, я полагаю, это список синонимов, созданных в этой схеме.
Профиль запроса в двух точках запроса:
Я открыл билет с Microsoft.
Кроме того, мы попытались добавить UserB в db_owner
, а затем использовать DENY
все известные нам привилегии, связанные с db_owner
. Результатом является быстрый запрос. Либо мы что-то пропустили (вполне возможно), либо есть специальная проверка на db_owner
роль.