我有一个SQL请求,通常执行时间少于1.5秒。但有时,它需要超过30秒,这种行为持续数小时。
以下是实际要求:
set dateformat ymd;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT Categories.Id as CategoryId,
(
CASE when VeryBigChildTable.Type = 9
then
Categories.Name
else
NULL
end
) as CategoryName,
OS1.Id,
OS1.StartDateUTC,
VeryBigChildTable.StartDateUTC as StartDateUTCSP,
Categories.Client_Id,
VeryBigChildTable.ArticleScriptArticleSPError_ArticleSP_Id as FailedStep,
VeryBigChildTable.[Order] as Position,
(
CASE when Categories.Id IS null
then
( cast(TSHeaders.Id as varchar(3)) + '__' + cast(OS1.Id as varchar(15) ))
else
( cast(Categories.Id as varchar(3)) + '_' + cast(OS1.Id as varchar(15) ))
end )
as GroupKey,
(
CASE when VeryBigChildTable.Type = 9
then
TSHeaders.CurrentName
else
NULL
end
) ,
SPHeaders.Id,
stuff((
SELECT '|' + ArticleCategories.Name
from ArticleCategories
inner join ArticleCategoryArticleScript
on ArticleCategoryArticleScript.BigTable_Id = OS1.Id
and ArticleCategoryArticleScript.ArticleCategories_Id = ArticleCategories.Id
for xml path('')),1,1,'')
from BigTable as OS1
inner join VeryBigChildTable on VeryBigChildTable.ArticleScript_Id = OS1.Id
inner join TSHeaders on TSHeaders.Id = OS1.TSArticle_Id
inner join SPHeaders on SPHeaders.Id = VeryBigChildTable.SPHeader_Id
inner join Categories on Categories.TSHeader_Id = OS1.TSArticle_Id
left outer join ArticleNetworks on ArticleNetworks.ArticleSPArticleNetwork_ArticleNetwork_Id = VeryBigChildTable.Id
where
OS1.StartDateUTC >= '2015-06-18 10:12:15'
and OS1.StartDateUTC <= '2015-06-19 10:12:15'
and TSHeaders.Id in (319,318,322,323,324,326,328,343,345,346,347,550,552,561,565,595,612,613)
and Categories.Id in (494,491,484,487,511,235,241,245,265,539,540,242,236,239,240,267,268,269)
此查询返回约20K行。
VeryBigChildTable
是2.6亿行表,BigTable
是6亿行表。其他表非常小(不到2K行)。
我的配置:Windows 2008 Server,Xeon 16核心和32GB RAM上的SQL Server 2008 R2(镜像)。
可能导致此请求运行的时间有时超过30秒? (知道在此期间我没有找到任何索引任务)
如何优化此请求?
欢迎你发表评论。
答案 0 :(得分:2)
可能有很多原因。
is_idle
标记,例如:SELECT * FROM sys.dm_os_schedulers WHERE scheduler_id <= 256
SELECT * FROM sys.dm_exec_query_memory_grants
。也许你会看到更多的查询请求内存。您还可以查看SELECT * FROM sys.dm_os_process_memory
。RECOMPILE
尝试OPTION(RECOMPILE)
您的查询,以获得符合当前情况的新查询计划。答案 1 :(得分:2)
如果这种情况不时发生,并且除了一个查询之外似乎其他一切工作正常,我的猜测是由于某种原因查询有一个新的查询计划。可以肯定的是,我建议检查查询计划的正常情况以及性能不佳时的情况。
要在流程运行时获取查询计划,您可以使用以下内容:
public ActionResult LoadFile(string path)
{
byteArray imageBytes = ....get img from blob storage
return File(byteArray, "image/png", "filename.ext");
}
如果您想检查发生了什么,并且稍后获得查询计划,您可以查看dm_exec_query_stats。它还显示了很好的统计信息,例如总逻辑读取,工作时间和每个语句的执行计数:
SELECT qp.*
FROM sys.dm_exec_requests r
cross apply sys.dm_exec_query_plan(r.plan_handle) qp
WHERE session_id = <spid of the process here>;
统计信息仅适用于缓存中存在的那些计划,因此如果由于某种原因计划被淘汰,统计信息也会丢失。