【问题标题】:A query that does a lot of reads, but plan is OK执行大量读取但计划正常的查询
【发布时间】:2014-10-06 15:40:18
【问题描述】:

我在SQL Server 2008 R2 的特定查询中遇到了奇怪的行为。 我有一个执行 1900 万次读取的查询并且非常耗时,当我尝试检查其缓存计划时,该计划是正常的,没有任何问题。

在执行DBCC FREEPROCCACHE 之后,相同的查询执行 400 次读取(耗时 16 毫秒)。 结论是查询以错误的计划执行,但这不是我从 SQL Server 获得的信息。

有人知道发生了什么吗? 在下面找到我用来提取计划的查询:

SELECT
sqltext.TEXT,
sqlplan.query_plan,
req.session_id [Session ID],
p.kpid [Thread ID],
p.program_name,
req.status,
req.command,
req.cpu_time,
req.logical_reads,
req.blocking_session_id,
req.transaction_id,
req.total_elapsed_time,
req.wait_resource
FROM sys.dm_exec_requests req inner join
     sys.sysprocesses p on req.session_id = p.spid
     CROSS APPLY sys.dm_exec_query_plan(req.plan_handle) AS sqlplan
     CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) AS sqltext

还有

SELECT db.name,
cp.objtype AS ObjectType,
OBJECT_NAME(st.objectid,st.dbid) AS ObjectName,
cp.usecounts AS ExecutionCount,
st.TEXT AS QueryText,
qp.query_plan AS QueryPlan
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st 
INNER JOIN sys.sysdatabases db on st.dbid = db.dbid
where st.TEXT like '%part_of_query%'

另外一个信息是free cache命令前后的查询计划是一样的。

Image of the Execution Plan

【问题讨论】:

  • 如果您还没有这样做,您也可以考虑在 dba.stackexchange.com 上询问。
  • 我刚做了,谢谢你的建议。
  • 发布两次运行的 STATISTICS IO 输出。
  • 请将该信息编辑到您的问题中,而不是将其发布为 cmets。
  • 即使计划形状可能保持不变或计划被重复使用,它也可能受到参数嗅探或统计数据偏斜的影响。仅仅因为它是相同的计划并不意味着它是正确的计划。如果您可以发布两次执行的实际计划,那将非常有帮助。

标签: sql-server sql-execution-plan


【解决方案1】:

很多事情都会以这种方式影响查询。最常见的可能是参数嗅探。当第一次执行查询时,计划是使用这些精确参数值得到的基数估计来构建的。 因此,如果第一次运行时使用的参数值非常有选择性,优化器可能会使用嵌套循环进行连接。所以下一次,用另一个值影响半张表,这个缓存的计划将非常无效,因为在这种情况下哈希或合并连接更好。

过时的分布统计也可能导致这种行为。以及碎片化的索引。可能还有一些其他的可能性——没有看到实际的执行计划,猜测可能会一直持续下去。

但您可以尝试在查询中添加optimize for unknown 选项,看看是否有帮助。

【讨论】:

    猜你喜欢
    • 2022-01-26
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多