У меня есть хранимая процедура, которая возвращает результаты из индексированного представления через индекс покрытия. Обычно он работает быстро (~ 10 мс), иногда он может работать до 8 секунд.
Вот пример случайного выполнения (примечание: это не медленное выполнение, но текст запроса не отличается от значения, переданного через):
declare @p2 dbo.IdentityType
insert into @p2 values(5710955)
insert into @p2 values(5710896)
insert into @p2 values(5710678)
insert into @p2 values(5710871)
insert into @p2 values(5711103)
insert into @p2 values(6215197)
insert into @p2 values(5710780)
exec ListingSearch_ByLocationAndStatus @statusType=1,@locationIds=@p2
Вот SPROC:
ALTER PROCEDURE [dbo].[ListingSearch_ByLocationAndStatus]
@LocationIds IdentityType READONLY,
@StatusType TINYINT
AS
BEGIN
SET NOCOUNT ON;
SELECT -- lots of fields
FROM [dbo].[ListingSearchView][a] WITH (NOEXPAND)
INNER JOIN @LocationIds [b] ON [a].[LocationId] = [b].[Id]
WHERE [a].[StatusType] = @statusType
OPTION (RECOMPILE);
(примечание: я добавил OPTION (RECOMPILE)
подсказку недавно после некоторых советов, но это не помогло.
Вот индекс покрытия (примечание: представление также имеет кластерный индекс ListingId
, который является уникальным)
CREATE NONCLUSTERED INDEX [IX_ListingSearchView_ForAPI] ON [dbo].[ListingSearchView]
(
[LocationId] ASC,
[StatusType] ASC
)
INCLUDE ( -- all the fields in the query) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
Я включил трассировку профайлера с XML-статистикой showplan.
Вот медленный (6 секунд) и соответствующий план:
Выглядит точно так, как я ожидал, и тот же план, когда запрос быстрый.
Вот увеличение дорогостоящей части плана, если это поможет:
Вот полная схема просмотра / поддержки таблиц, если это поможет: https://pastebin.com/wh1sRcbQ
Примечания:
- Индексы были дефрагментированы, статистика актуальна.
- Первоначально запрос был встроен в представление, но я перешел в SPROC, чтобы попытаться помочь в стабилизации. Не помогло
- Добавление
WITH OPTION (RECOMPILE);
подсказки (не сработало, поэтому не может быть сниффинг параметров?) - Другие запросы в системе также иногда выполняются медленно, и у них также нет очевидных проблем в их плане.
- Может быть блокировка? Не уверен, как подтвердить.
Любые идеи о том, что я мог бы попробовать дальше?
Благодарность
Ответы:
Я действительно не думаю, что использование
OPTION (RECOMPILE)
- эффективный способ устранить возможность перехвата параметров.Перехват параметров происходит, когда SQL запутывается в конкретном запросе и считает его новым, потому что видит новые параметры. Это медленно, потому что требуется дополнительное время для генерации нового плана выполнения.
Все, что делает эта опция, это заставляет SQL каждый раз создавать новый план, что в значительной степени одно и то же. Вместо этого вы можете рассмотреть возможность добавления параметров по умолчанию, используя эту подсказку:
При выборе параметров по умолчанию обязательно используйте статистически репрезентативный набор.
Это заставит каждый раз использовать один и тот же план и исключит возможность перехвата параметров. Как только вы сделаете это, и определите, что это не помогло, тогда, вероятно, безопасно отклонить анализ параметров как возможность.
источник
Возможно, попытайтесь форсировать порядок, так что вы, вероятно, всегда начинаете с меньшей таблицы (переменной). Это сложно с взглядами, хотя ...
или вы можете принудительно соединить цикл, если вы хотите соединить переменную таблицы с представлением, что также приведет к порядку ...
источник
Запишите имя процедуры Store в редакторе запросов, затем выберите процедуру Store. имя и затем выберите Показать план предполагаемого выполнения или нажмите (Ctrl + L). под изображением этого.
затем планы выполнения отображаются рядом с вкладкой «Сообщения» в нижней части редактора запросов. затем в зеленых цветных линиях покажите недостающие детали индекса и щелкните по нему правой кнопкой мыши. Затем Новый запрос откройте в новой вкладке, затем создайте ИНДЕКС. тогда ваш запрос выполняется быстро.
Поэтому я использовал этот метод для диагностики запросов, которые работают медленно. а также есть так много запросов или методов, которые вы можете использовать.
источник
Если вы считаете, что проблема заключается в блокировке, я предлагаю вам использовать оптимистический уровень изоляции транзакции Read Committed Snapshot (имейте в виду, что это приведет к накладным расходам на вашу базу данных tempDB).
СПРАВКА: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server
Если проблема не в блокировке чтения / записи, вы можете попробовать добавить индексы на ваше представление (лучший выбор индексов зависит от селективности ваших данных)
источник
IX_ListingSearchView_ForAPI
(см. Сценарий в вопросе).