搜索表/索引扫描

发布于 2024-08-07 16:06:10 字数 66 浏览 5 评论 0原文

是否有人有一个查询可以搜索 SQL2005/2008 的计划缓存来识别在其执行计划中具有表/索引扫描的查询或存储过程?

Does anyone have a query which searches through SQL2005/2008's plan cache identifying queries or stored procedures which have table/index scans within their execution plans?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无所谓啦 2024-08-14 16:06:10

Pinal Dave 实际上发表了一篇关于此问题的文章,并对他的原始文章进行了一些修改(几乎不需要任何修改!),您可以获得正确的答案。如果他有帐户,请相信他:)

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,但公平地说,Pinal 做了一个很棒的版本,所以我们不要重新发明它。

Pinal Dave actually did a post about this and with a bit of alteration on his original article (barely any alteration required!) you can get the right answer. If he's got an account, credit him :)

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/

His Query is:

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 what you want on the end is specifically the scan types (Clustered, Table and Index)

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

The basic query to get the plan cache isn't hard, and you can manually kruft the XQuery, but to be fair, Pinal did a great version of it so lets not reinvent it.

记忆で 2024-08-14 16:06:10

我花了一段时间才说服它给我答案,但最终只是一个小小的改变。如果您想要导致扫描的对象名称,那么可以完成,但存在问题。

有件事限制了它的有效性。 Object_Name / sys.Objects 的范围是您的数据库,因此您将从任何数据库的缓存中提取所有计划,但只能命名您当前正在使用的数据库内的计划。

不保证对象 ID 在数据库之间是唯一的,因此给定的 ID 有可能与您当前的数据库以及另一个数据库匹配,并且您会得到它返回的错误名称,因此它无论如何都不完美。

同样,如果您看到任何对象 ID > > 的内容, 0 但未给出名称意味着该计划来自对象而不是即席查询,但有关该名称的信息位于服务器内不同数据库的系统视图中。

在单个数据库内的服务器上,它至少是正确的,但将它给您的名称作为指示,而不是福音。

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'
)

That's taken a while to convince it to give me the answer but it is a minor alteration in the end. If you want the object name that is causing the scan then it cane be done, but there are problems.

There is one thing that is limiting the effectiveness of it. The scope of Object_Name / sys.Objects is to your database, so you are pulling all the plans from the cache for any database, but can only name those that are within the database you are currently using.

Object IDs are not guarenteed to be unique between databases so there is a chance the ID given matches to your current database, as well as another and you would get an incorrect name returned by it, so it is not perfect by any means.

Equally, if you see anything with an object ID > 0 but no name given means the plan was from an object not an adhoc query, but the information about that name is in a system view on a different database within the server.

On a server within a single DB it would be correct at least, but take the name it gives you as an indication, not gospel.

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'
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文