Сценарий: 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
роль.
access check cache bucket count
иaccess check cache quota
ранее. Придется немного поиграться с этими.WHILE(1=1) BEGIN DBCC FREESYSTEMCACHE ('TokenAndPermUserStore') WAITFOR DELAY '00:00:05' END
в цикле навсегда, запрос будет завершен менее чем за 2 минуты против 8 минут обычно.Если это все еще живо - у нас возникла та же проблема - похоже, что если вы либо dbo, либо системный администратор, то любой доступ к sys.objects (или что-то в этом роде) - тогда это происходит мгновенно, без проверок отдельных объектов.
если это скромный db_datareader, то он должен проверять каждый объект по очереди ... он скрыт в плане запросов, так как они ведут себя больше как функции, чем представления / таблицы
план выглядит так же, но он делает разные вещи за капотом
источник
Использование флага трассировки 9481, кажется, решает эту проблему для меня.
CE (Cardinality Estimator) в 2014 году (Compat 120) изменился по сравнению с 2012 и 2008 годами, и использование TF 9481 заставляет использовать CE 2012 года.
См. «Оценщик количества элементов SQL 2014», «Кушает плохой TSQL на завтрак » Кендры Литтл.
источник