Постійне сканування займає або 0 секунд, або 2-3 хвилини


9

Запит, на зразок наведеного нижче, гарантовано не повертає жодних рядків, займає від 0 до 160 секунд на одному з наших серверів:

select col1, col2, col3
from tab1
where 0 = 1

Два тижні тому це сталося шість разів з інтервалом 48 годин. Минулого тижня цей же запит зайняв ~ 0 секунд. У мене є журнали SQL нашої програми, але ще не знайдено підозрюваних. Крім того, я вважав, що зверху 0 / де 0 = 1 запит ніколи не потрапляє на сторінки даних, тож він повинен бути стійким до блокувань даних на рівні рядків / сторінок / таблиці? Схему не торкаються жодні (відомі) SQL.

Оскільки проблема не узгоджується, і сервер перебуває під дуже великим навантаженням, я хотів би зрозуміти теорію того, що відбувається перед тим, як приєднати SQL-профілер. Інші запити виконуються без проблем під час цих затримок. Відома проблема в додатку - велика кількість динамічно створених SQL-запитів - близько 200 тис. Унікальних запитів загальною кількістю 850 к (записів) протягом 48 годин, чи можуть це викликати подібні проблеми?

На сервері працює стандартне видання SQL Server 2005, 96 ГБ оперативної пам’яті, диски на SAN та 4 процесори / 16 ядер. Файли баз даних і групи файлів добре оптимізовані, і це не повинно бути проблемою (але ми розглядаємо це окремо).

Будь-які вказівки, де їх шукати, дуже вдячні.

Редагувати: Ідеально! Відтворено запит, щоб додати план виконання, і на це пішло 1 хв 35 сек. Ось план виконання та скріншот із зображенням тривалості запиту: План запитів

Редагувати 2: детальна інформація про час другого циклу. Зараз, здається, постійно повільно, тому ми додамо профайлер і парфмон:

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 97402 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

Чи можете ви включити план виконання? CTRL + M у вікні запиту перед виконанням.
Крейг Ефрейн

2
Чи може це бути проблемою блокування? Висловлювання DML з інших сеансів, що блокують вибір у таблиці (що є поведінкою за замовчуванням у SQL Server 2005)
a_horse_with_no_name

Немає жодних невідомих-DML-тверджень, що є єдиною причиною, про яку я можу подумати, але ми все ще досліджуємо це. План виконання додається до питання.
EventHorizon

З того, що я прочитав, це лише один із тих тривіальних планів виконання, які MSSQL використовує, щоб уникнути читання купи та індексів, коли оптимізатор знає, що немає рядків, які потрібно повернути
Craig Efrein

1
Бачив випадок, який виглядав приблизно так. Виявилося, що це ініціює статистику оновлення (увімкнено статистику автоматичного оновлення та план технічного обслуговування порушено).
Джошуа

Відповіді:


18

Схоже, навіть із ... WHERE 0 = 1застереженням про те, що все ще буде вимога щодо наміру ISзаблокованого ( ) блокування на столі. Доведемо це:

Почну зі створення тестової таблиці:

use TestDb1;
go

create table dbo.MyTestTable1
(
    Id int identity(1, 1) not null,
    SomeInt int not null
);
go

insert into dbo.MyTestTable1 (SomeInt)
values (10), (20), (30), (40), (50);
go

Тепер, коли у мене є моя тестова таблиця, за один сеанс (вікно запиту) я виконую наступне, щоб поставити ексклюзивний ( X) замок dbo.MyTestTable1:

use TestDb1;
go

begin tran;
    select
        Id, SomeInt
    from dbo.MyTestTable1 with (tablockx);
--commit tran;

Я можу перевірити ексклюзивний замок, поглянувши на sys.dm_tran_locksDMV. Потім в іншому сеансі (нове вікно запиту) я роблю саме те, що робить ваш запит:

use TestDb1;
go

select
    Id, SomeInt
from dbo.MyTestTable1
where 0 = 1;

З першого погляду я бачу, що це не закінчується. Дивлячись sys.dm_exec_requests, я точно бачу, чому це так:

select
    r.session_id,
    r.status,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    r.blocking_session_id
from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(r.sql_handle) st
where st.text like '%where 0 = 1%'
and r.session_id <> @@spid;

введіть тут опис зображення

Я бачу тут, що мій ... WHERE 0 = 1запит очікує на ISзамок для цього об’єкта (це object_id перекладається dbo.MyTestTable1).

Я ні в якому разі не кажу, що паралельність - це ваша проблема, але, звучаючи її, ви проявляєте симптоми. Наведений вище приклад - довести, що ви не звільняєтесь від блокування та блокування навіть із WHEREпунктом, який ніколи не повертає дані.

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


1

Залежно від того, наскільки колоситими і нитки вимагають ваших запитів, ваша система може просто поставити в чергу цей запит. Кількість робітників за замовчуванням (тобто кількість одночасних потоків сервера SQL) для вашої установки повинна становити близько 700.

Перевірте sys.dm_os_schedulers та sys.dm_os_waiting_tasks, щоб побачити, чи це може бути проблемою.


Хороша пропозиція, але проблема зрештою стала дурним замком.
EventHorizon

Я не був дуже впевнений, оскільки 700 працівників достатньо, але це було легко перевірити (і, таким чином, виключити)
Sascha Rambeaud
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.