Измерение эффективности запросов: "Стоимость запроса плана выполнения" против "Время, затраченное",
Я пытаюсь определить относительную производительность двух разных запросов и имею два способа измерения этого для меня:
1. Запустите оба и время каждого запроса
2. Запустите оба и получите "Стоимость запроса" из фактического плана выполнения
Вот код, который я запускал во время запросов...
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
DECLARE @start DATETIME SET @start = getDate()
EXEC test_1a
SELECT getDate() - @start AS Execution_Time
GO
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
DECLARE @start DATETIME SET @start = getDate()
EXEC test_1b
SELECT getDate() - @start AS Execution_Time
GO
Я получаю следующее:
Stored_Proc Execution_Time Query Cost (Relative To Batch)
test_1a 1.673 seconds 17%
test_1b 1.033 seconds 83%
Результаты времени выполнения напрямую противоречат результатам Стоимость запроса, но мне сложно определить, что означает "стоимость запроса". Мое лучшее предположение заключается в том, что это совокупность Reads/Writes/CPU_Time/и т.д., Поэтому я думаю, у меня есть пара вопросов:
-
Есть ли определенный источник, чтобы объяснить, что означает эта мера?
-
Какие еще показатели производительности "Query Performance" используются людьми и каковы их относительные достоинства?
Возможно, важно отметить, что это SQL Server среднего размера, работающий под управлением MS SQL Server 2005 на MS Server 2003 Enterprise Edition с несколькими процессорами и более 100 одновременных пользователей.
EDIT:
После некоторого беспокойства мне удалось получить доступ к Profiler на этом SQL Server и может предоставить дополнительную информацию (которая поддерживает стоимость запроса, связанную с системными ресурсами, а не самим временем выполнения)
Stored_Proc CPU Reads Writes Duration
test_1a 1313 3975 93 1386
test_1b 2297 49839 93 1207
Впечатляет, что с большим количеством процессоров с МНОГИМ Чтение занимает меньше времени:)
Ответы
Ответ 1
Трассировка профайлера помещает его в перспективу.
- Запрос A: процессор с частотой 1,3 секунды, длительность 1.4 сек.
- Query B: процессор с частотой 2,3 секунды, длительность 1,2 секунды
В запросе B используется parallelism: CPU > duration
например, в запросе используются 2 процессора, в среднем по 1,15 с каждый
Запрос A, вероятно, нет: CPU < Продолжительность
Это объясняет стоимость относительно партии: 17% для более простого плана непараллельных запросов.
Оптимизатор определяет, что запрос B является более дорогим и будет полезен parallelism, хотя для этого требуются дополнительные усилия.
Помните, что этот запрос B использует 100% 2 CPUS (так 50% для 4 процессоров) в течение одной секунды или около того. Запрос A использует 100% одного процессора в течение 1,5 секунд.
Пик для запроса А ниже, за счет увеличения продолжительности.
С одним пользователем, кого это волнует? С 100, возможно, это имеет значение...
Ответ 2
SET STATISTICS TIME ON
SELECT *
FROM Production.ProductCostHistory
WHERE StandardCost < 500.00;
SET STATISTICS TIME OFF;
И посмотрите вкладку с сообщением, она будет выглядеть так:
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 10 ms.
(778 row(s) affected)
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
Ответ 3
Результаты времени выполнения напрямую противоречат результатам Стоимость запроса, но мне сложно определить, что означает "стоимость запроса".
Query cost
- это то, что оптимизатор думает о том, сколько времени займет ваш запрос (относительно общего времени партии).
Оптимизатор пытается выбрать оптимальный план запроса, просматривая ваш запрос и статистику ваших данных, пытаясь выполнить несколько планов выполнения и выбрав наименее дорогостоящие из них.
Здесь вы можете более подробно прочитать, как он пытается это сделать.
Как вы можете видеть, это может существенно отличаться от того, что вы на самом деле получаете.
Единственная реальная метрика выполнения запросов - это, конечно, сколько времени действительно занимает запрос.
Ответ 4
Используйте SET STATISTICS TIME ON
над вашим запросом.
Внизу рядом с вкладкой результатов вы можете увидеть вкладку сообщений. Там вы можете увидеть время.
Ответ 5
Я понимаю его старый вопрос - однако я хотел бы добавить пример, где стоимость такая же, но один запрос лучше, чем другой.
Как вы заметили в вопросе,%, показанное в плане выполнения, не является единственным критерием для определения наилучшего запроса. В следующем примере у меня есть два запроса, выполняющих одну и ту же задачу. План выполнения показывает, что оба одинаково хороши (по 50%). Теперь я выполнил запросы с SET STATISTICS IO ON
, который показывает явные отличия.
В следующем примере запрос 1 использует seek
, тогда как Query 2 использует scan
в таблице LWManifestOrderLineItems. Когда мы фактически проверяем время выполнения, однако обнаруживаем, что Query 2 работает лучше.
Также читайте Когда ищут не искание? Paul White
QUERY
---Preparation---------------
-----------------------------
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
SET STATISTICS IO ON --IO
SET STATISTICS TIME ON
--------Queries---------------
------------------------------
SELECT LW.Manifest,LW.OrderID,COUNT(DISTINCT LineItemID)
FROM LWManifestOrderLineItems LW
INNER JOIN ManifestContainers MC
ON MC.Manifest = LW.Manifest
GROUP BY LW.Manifest,LW.OrderID
ORDER BY COUNT(DISTINCT LineItemID) DESC
SELECT LW.Manifest,LW.OrderID,COUNT( LineItemID) LineCount
FROM LWManifestOrderLineItems LW
WHERE LW.Manifest IN (SELECT Manifest FROM ManifestContainers)
GROUP BY LW.Manifest,LW.OrderID
ORDER BY COUNT( LineItemID) DESC
Статистика IO
![введите описание изображения здесь]()
План выполнения
![введите описание изображения здесь]()
Ответ 6
Время выполнения запроса:
DECLARE @EndTime datetime
DECLARE @StartTime datetime
SELECT @StartTime=GETDATE()
` -- Write Your Query`
SELECT @EndTime=GETDATE()
--This will return execution time of your query
SELECT DATEDIFF(MILLISECOND,@StartTime,@EndTime) AS [Duration in millisecs]
Вывод запроса будет следующим:
![enter image description here]()
Чтобы оптимизировать стоимость запроса:
Нажмите на свою студию управления SQL
![enter image description here]()
Запустите свой запрос и нажмите "План выполнения" рядом с вкладкой "Сообщения" вашего результата запроса. вы увидите как
![enter image description here]()