Хоча я, як і @Thomas, повністю погоджуюся з @Aaron в коментарях до питання щодо того, що "використання CPU на базі даних" є точним або корисним, я можу принаймні відповісти на питання, чому ці два запити так інший. І причина, чому вони відрізняються, вкаже, хто з них точніший, хоча той рівень вищої точності все ще відносно того, який є конкретно неточним, отже, все ще не справді точним ;-).
Перший запит використовує sys.dm_exec_query_stats для отримання інформації про процесор (тобто total_worker_time
). Якщо ви перейдете на пов’язану сторінку, що є документацією MSDN для цього DMV, ви побачите короткий вступ із 3 реченнями та 2 з цих речень, які дають нам більшу частину того, що нам потрібно для розуміння контексту цієї інформації ("наскільки це надійно" і "як воно порівнюється з sys.sysprocesses
"). Ці два речення:
Повертає сукупну статистику продуктивності для кешованих планів запитів у SQL Server. ... Коли план вилучається з кешу, відповідні рядки видаляються з цього виду
Перше речення, "Повертає сукупну статистику ефективності", говорить про те, що інформація в цьому DMV (так само, як і в кількох інших) є сукупною і не специфічна лише для запитів, які зараз запущені. На це вказується також поле в тому DMV, яке не є частиною запиту у запитанні execution_count
, яке ще раз показує, що це сукупні дані. І досить зручно, щоб ці дані були накопичувальними, оскільки ви можете отримати середні показники тощо, розділивши деякі показники на execution_count
.
Друге речення: "плани, які вилучаються з кеша, також видаляються з цього DMV", вказують на те, що це зовсім не повне уявлення, особливо якщо сервер вже має досить повний кеш плану і навантажений, а значить, терміни закінчуються дещо часто. Крім того, більшість DMV скидаються під час скидання сервера, щоб вони не були справжньою історією, навіть якщо ці рядки не були видалені після закінчення терміну дії планів.
Тепер давайте порівняємо вищезгадане sys.sysprocesses
. Цей системний вигляд відображає лише те, що зараз працює, як і комбінацію sys.dm_exec_connections , sys.dm_exec_sesions та sys.dm_exec_requests (що зазначено на пов'язаній сторінці для sys.dm_exec_sessions
). Це зовсім інший погляд на сервер порівняно з sys.dm_exec_query_stats
DMV, який зберігає дані навіть після завершення процесу. Значить, стосовно "чи невірні результати другого запиту?" питання, вони не помиляються, вони просто стосуються іншого аспекту (тобто часових рамок) статистики результативності.
Отже, запит із використанням sys.sysprocesses
дивиться лише на "прямо зараз". І запит, що використовує sys.dm_exec_query_stats
, в основному розглядає (можливо) те, що сталося з моменту останнього перезавантаження служби SQL Server (або, очевидно, перезавантаження системи). Для загального аналізу продуктивності здається, що sys.dm_exec_query_stats
це набагато краще, але знову ж таки, він весь час опускає корисну інформацію. І в обох випадках вам також потрібно врахувати пункти, зроблені @Aaron, у коментарях до запитання (з моменту видалення) щодо точності значення "database_id" в першу чергу (тобто воно відображає лише активну БД, яка ініціювала код , не обов'язково там, де відбувається "питання").
Але, якщо вам просто потрібно / хочу , щоб отримати уявлення про те , що відбувається прямо зараз у всіх базах даних, можливо , тому , що речі сповільнюються прямо зараз, ви краще використовувати комбінацію з sys.dm_exec_connections
, sys.dm_exec_sessions
і sys.dm_exec_requests
(і не рекомендується sys.sysprocesses
). Просто майте на увазі, що ви шукаєте / для запитів , а не баз даних , оскільки запити можуть об'єднуватися в декілька баз даних, включати UDF з однієї або декількох баз даних тощо.
EDIT:
Якщо загальне занепокоєння скорочує високих споживачів процесора, то шукайте запити, які займають найбільше CPU, оскільки бази даних насправді не займають процесор (дивлячись на одну базу даних, можливо, працює в хостинг-компанії, де кожна база даних ізольована і належить іншому замовнику).
Наступний запит допоможе визначити запити з високим середнім рівнем використання процесора. Це стискає дані в DMV запиту_статів, оскільки ці записи можуть показувати один і той же запит (так, однаковий підмножина пакету запитів) кілька разів, кожен з іншим планом виконання.
;WITH cte AS
(
SELECT stat.[sql_handle],
stat.statement_start_offset,
stat.statement_end_offset,
COUNT(*) AS [NumExecutionPlans],
SUM(stat.execution_count) AS [TotalExecutions],
((SUM(stat.total_logical_reads) * 1.0) / SUM(stat.execution_count)) AS [AvgLogicalReads],
((SUM(stat.total_worker_time) * 1.0) / SUM(stat.execution_count)) AS [AvgCPU]
FROM sys.dm_exec_query_stats stat
GROUP BY stat.[sql_handle], stat.statement_start_offset, stat.statement_end_offset
)
SELECT CONVERT(DECIMAL(15, 5), cte.AvgCPU) AS [AvgCPU],
CONVERT(DECIMAL(15, 5), cte.AvgLogicalReads) AS [AvgLogicalReads],
cte.NumExecutionPlans,
cte.TotalExecutions,
DB_NAME(txt.[dbid]) AS [DatabaseName],
OBJECT_NAME(txt.objectid, txt.[dbid]) AS [ObjectName],
SUBSTRING(txt.[text], (cte.statement_start_offset / 2) + 1,
(
(CASE cte.statement_end_offset
WHEN -1 THEN DATALENGTH(txt.[text])
ELSE cte.statement_end_offset
END - cte.statement_start_offset) / 2
) + 1
)
FROM cte
CROSS APPLY sys.dm_exec_sql_text(cte.[sql_handle]) txt
ORDER BY cte.AvgCPU DESC;
AvgCPU
в мілісекундах?