Поиск таблицы / индекса сканирования - PullRequest
5 голосов
/ 09 октября 2009

Есть ли у кого-нибудь запрос, который просматривает кэш планов SQL2005 / 2008, идентифицирующий запросы или хранимые процедуры, которые имеют таблицы / индексы в своих планах выполнения?

Ответы [ 2 ]

5 голосов
/ 09 октября 2009

Пинал Дейв действительно написал сообщение об этом, и с небольшим изменением в его оригинальной статье (без каких-либо изменений!) Вы можете получить правильный ответ. Если у него есть аккаунт, кредитуйте его:)

http://blog.sqlauthority.com/2009/03/17/sql-server-practical-sql-server-xml-part-one-query-plan-cache-and-cost-of-operations-in-the-cache/

Его запрос:

WITH XMLNAMESPACES(DEFAULT N'http://schemas.microsoft.com/sqlserver/2004/07/showplan'),
CachedPlans
(
ParentOperationID,
OperationID,
PhysicalOperator,
LogicalOperator,
EstimatedCost,
EstimatedIO,
EstimatedCPU,
EstimatedRows,
PlanHandle,
QueryText,
QueryPlan,
CacheObjectType,
ObjectType)
AS
(
SELECT
RelOp.op.value(N'../../@NodeId', N'int') AS ParentOperationID,
RelOp.op.value(N'@NodeId', N'int') AS OperationID,
RelOp.op.value(N'@PhysicalOp', N'varchar(50)') AS PhysicalOperator,
RelOp.op.value(N'@LogicalOp', N'varchar(50)') AS LogicalOperator,
RelOp.op.value(N'@EstimatedTotalSubtreeCost ', N'float') AS EstimatedCost,
RelOp.op.value(N'@EstimateIO', N'float') AS EstimatedIO,
RelOp.op.value(N'@EstimateCPU', N'float') AS EstimatedCPU,
RelOp.op.value(N'@EstimateRows', N'float') AS EstimatedRows,
cp.plan_handle AS PlanHandle,
st.TEXT AS QueryText,
qp.query_plan AS QueryPlan,
cp.cacheobjtype AS CacheObjectType,
cp.objtype AS ObjectType
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) qp
CROSS APPLY qp.query_plan.nodes(N'//RelOp') RelOp (op)
)
SELECT
PlanHandle,
ParentOperationID,
OperationID,
PhysicalOperator,
LogicalOperator,
QueryText,
CacheObjectType,
ObjectType,
EstimatedCost,
EstimatedIO,
EstimatedCPU,
EstimatedRows
FROM CachedPlans
WHERE CacheObjectType = N'Compiled Plan'

И, в конце концов, вам нужны именно типы сканирования (кластеризованный, таблица и индекс)

and
(PhysicalOperator = 'Clustered Index Scan' or PhysicalOperator = 'Table Scan' 
or PhysicalOperator = 'Index Scan')

Основной запрос для получения кэша плана не сложен, и вы можете вручную взломать XQuery, но, честно говоря, Пинал сделал отличную версию, поэтому не будем изобретать его заново.

3 голосов
/ 14 октября 2009

Потребовалось некоторое время, чтобы убедить его дать мне ответ, но это незначительное изменение в конце. Если вам нужно имя объекта, который вызывает сканирование, это можно сделать, но есть проблемы.

Есть одна вещь, которая ограничивает эффективность этого. Область действия Object_Name / sys.Objects относится к вашей базе данных, поэтому вы извлекаете все планы из кэша для любой базы данных, но можете назвать только те, которые находятся в базе данных, которую вы используете в данный момент.

Не гарантируется, что идентификаторы объектов будут уникальными между базами данных, поэтому существует вероятность того, что данный идентификатор соответствует вашей текущей базе данных, а также другой, и вы получите неверное имя, возвращаемое им, поэтому оно не является совершенным ни при каких условиях. .

Точно так же, если вы видите что-либо с идентификатором объекта> 0, но имя не указано, значит, план был от объекта, а не от запроса adhoc, но информация об этом имени находится в системном представлении другой базы данных на сервере.

На сервере в пределах одной БД это было бы правильно, по крайней мере, но примите имя, которое оно дает вам в качестве указания, а не Евангелие.

WITH XMLNAMESPACES
(DEFAULT N'http://schemas.microsoft.com/sqlserver/2004/07/showplan'),
CachedPlans
(
ParentOperationID,
OperationID,
PhysicalOperator,
LogicalOperator,
EstimatedCost,
EstimatedIO,
EstimatedCPU,
EstimatedRows,
PlanHandle,
QueryText,
QueryPlan,
CacheObjectType,
ObjectType,
ObjectID)
AS
(
    SELECT
    RelOp.op.value(N'../../@NodeId', N'int') AS ParentOperationID,
    RelOp.op.value(N'@NodeId', N'int') AS OperationID,
    RelOp.op.value(N'@PhysicalOp', N'varchar(50)') AS PhysicalOperator,
    RelOp.op.value(N'@LogicalOp', N'varchar(50)') AS LogicalOperator,
    RelOp.op.value(N'@EstimatedTotalSubtreeCost ', N'float') AS EstimatedCost,
    RelOp.op.value(N'@EstimateIO', N'float') AS EstimatedIO,
    RelOp.op.value(N'@EstimateCPU', N'float') AS EstimatedCPU,
    RelOp.op.value(N'@EstimateRows', N'float') AS EstimatedRows,
    cp.plan_handle AS PlanHandle,
    st.TEXT AS QueryText,
    qp.query_plan AS QueryPlan,
    cp.cacheobjtype AS CacheObjectType,
    cp.objtype AS ObjectType,
    qp.objectid
    FROM sys.dm_exec_cached_plans cp
    CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
    CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) qp
    CROSS APPLY qp.query_plan.nodes(N'//RelOp') RelOp (op)
)

SELECT 
PlanHandle,
ParentOperationID,
OperationID,
PhysicalOperator,
LogicalOperator,
QueryText,
CacheObjectType,
ObjectType,
EstimatedCost,
EstimatedIO,
EstimatedCPU,
EstimatedRows,
QueryPlan,
C.ObjectID,
Object_Name(C.ObjectID)
FROM CachedPlans C
Where 
(PhysicalOperator = 'Clustered Index Scan' 
  or 
PhysicalOperator = 'Table Scan' 
 or 
PhysicalOperator = 'Index Scan'
)
...