Поради щодо діагностики "іноді" повільного запиту


20

У мене зберігається процедура, яка повертає результати з індексованого виду через індекс покриття. Зазвичай вона працює швидко (~ 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

Я помістив слід профілера зі статистикою showplan XML.

Ось повільний (6 секунд) та відповідний план: введіть тут опис зображення

Виглядає точно так, як я очікував, і це той самий план, коли запит швидкий.

Ось збільшити дорогу частину плану, якщо це допоможе: введіть тут опис зображення

Ось повна схема таблиць перегляду / резервного копіювання, якщо це допомагає: https://pastebin.com/wh1sRcbQ

Примітки:

  • Індекси були дефрагментовані, статистика оновлена.
  • Спочатку запит відповідав перегляду, але я перейшов до SPROC, щоб спробувати допомогти стабілізуватись. Не допомогло.
  • Додавання WITH OPTION (RECOMPILE);підказки (не спрацювало, тому не може бути нюхати параметри?)
  • Інші запити в системі також іноді працюють повільно, і вони також не мають очевидних проблем у своєму плані.
  • Може бути заблокованим? Не знаєте, як це підтвердити.

Будь-які ідеї, що я можу спробувати далі?

Спасибі


1
Коментарі не для розширеного обговорення; ця розмова переміщена до чату . Усі: Будь ласка, використовуйте цей інструмент для подальшого обговорення цього питання.
Пол Білий каже, що GoFundMonica

дана посилання не працює. Запит запиту прямий вперед, існує велика різниця між фактичною та передбачуваною кількістю рядків, що викликає занепокоєння. Я думаю, що проблема полягає в огляді запиту. Я думаю, недостатньо даних. Це повинно бути близько
KumarHarsh

Ви спробували запустити WhoIsActive (від Адама Маханіка) під час запуску запиту? whoisactive.com Він містить інформацію про завдання, що очікують, яка повинна спрямовувати вас у правильному напрямку.
MJH

Ви усунули щось зовнішнє для БД, що спричинило це. Можливо, якась інша програма, що викликає синхронний IO для зберігання даних, спільного з БД?
Йоган

Відповіді:


2

Я дійсно не думаю, що використання OPTION (RECOMPILE)методу є ефективним способом виключити можливість обнюхування параметрів.

Нюхання параметрів відбувається, коли SQL плутається з певного запиту і думає про його новий, оскільки бачить нові параметри. Це повільно, тому що для створення нового плану виконання потрібен додатковий час.

Все, що це робить, це змусити SQL кожного разу створювати новий план, що майже однаково. Натомість ви можете розглянути можливість додавання параметрів за замовчуванням за допомогою цього підказки:

OPTION(OPTIMIZE FOR(@LocationIds='xx',@StatusType='xx'))

Вибираючи параметри за замовчуванням, обов'язково використовуйте статистично репрезентативний набір.
Це змусить кожен раз використовувати один і той же план і виключить можливість обнюхування параметрів. Як тільки ви це зробите, і визначите, що це не допомогло, то, ймовірно, безпечно відхилити нюхання параметра як можливість.


1

Можливо, спробуйте примусити замовлення, тому ви, ймовірно, завжди починаєте з меншої таблиці (змінної). Це стає складним у поглядах, хоча ...

    SELECT  -- lots of fields
    FROM    @LocationIds [b] WITH (NOEXPAND)
            INNER JOIN  [dbo].[ListingSearchView][a] WITH (NOEXPAND) 
                ON [a].[LocationId] = [b].[Id]
    WHERE   [a].[StatusType] = @statusType
    OPTION (FORCE ORDER);

або ви можете примусити цикл приєднатися, якщо це, як правило, ви хочете приєднати змінну таблиці до перегляду, що також змусить замовити ...

    SELECT  -- lots of fields
    FROM    @LocationIds [b] WITH (NOEXPAND)
            INNER LOOP JOIN  [dbo].[ListingSearchView][a] WITH (NOEXPAND) 
                ON [a].[LocationId] = [b].[Id]
    WHERE   [a].[StatusType] = @statusType
    --leaving this here so you don't get an annoying warning 
    OPTION (FORCE ORDER);

0

Напишіть назву процедури магазину в редакторі запитів, а потім оберіть процедуру магазину. ім'я та потім оберіть Відобразити передбачуваний план виконання або клацніть (Ctrl + L). нижче зображення цього.

Зображення відображеного орієнтовного плану виконання

тоді Плани виконання відображаються біля вкладки Повідомлення внизу редактора запитів. тоді в зелених кольорових лініях відображаються відсутні дані про індекс та клацніть правою кнопкою миші на ньому. Потім відкрийте Новий запит у новій вкладці, потім створіть INDEX. то ваш Запит швидко працює.

Тому я використав цей метод для діагностики запитів, які працюють повільно. а також є так багато запитів або методів, які ви можете використовувати.

План виконання з деталями


-1

Якщо ви думаєте, що проблема полягає в блокуванні, я запропонував би вам скористатися оптимістичним рівнем ізоляції транзакцій Прочитайте Здійснений знімок (врахуйте, що це накладе накладні витрати на ваш tempDB).

ДОВІДКА: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server

Проблема полягає не в блокуванні читання / запису, ви можете спробувати додати індекси на свій погляд (найкращий вибір індексів залежить від вибірковості ваших даних)

CREATE NONCLUSTERED INDEX IX_ListingSearchView (LocationID, StatusType) INCLUDE (other columns...)

1
Індекс, який ви пропонуєте, вже існує IX_ListingSearchView_ForAPI(див. Сценарій у питанні).
Пол Білий каже, що GoFundMonica

1
Гей, дякую за вашу відповідь. Як я вже говорив у своєму запитанні, я хочу знати, у чому полягає проблема, перш ніж застосувати виправлення. Інакше я міг просто не помітити реальної проблеми. Моє запитання полягає у пошуку спочатку проблеми, а потім правильного рішення.
RPM1984

Чи можете ви отримати повільний запит у вашому місцевому середовищі? Якщо той же запит іноді працює повільно, а іноді працює швидко, це може залежати від вхідних параметрів. Чи можете ви вказати кількість логічних читань та загальну кількість рядків, повернених вашим повільним запитом.
Арташес Хачатрян

@ArtashesKhachatryan так, іноді це працює повільно і на місцевих. Я оновив запитання планом виконання. Мені цікаво, чи це пов’язано з повільними запитами, що повертають більше рядків, ніж швидкий, як ви вже говорили.
RPM1984
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.