[英]SQL Server query suddenly slow
我有一个SQL数据库查询的问题突然 (但通常大约每三周)变得缓慢。
安装程序如下:
Orders
)主要是从大约24000条记录中选择的,其他5条连接表都很小(100条记录以下) Orders
有一个varbinary(MAX)
列Report
,其中包含平均大小约为200到300 kB的二进制数据(PDF文档)(偶尔可以高达2 MB)。 这24000个订单中有90%以上填充了此列,其他订单为NULL
,即6 GB数据库大小的90%以上是二进制数据。 有问题的查询具有以下结构:
SELECT TOP (30) [Project2].[OrderID] AS [OrderID]
-- around 20 columns more
FROM ( SELECT [Project2].[OrderID] AS [OrderID],
-- around 20 columns more
row_number() OVER (ORDER BY [Project2].[OrderID] ASC) AS [row_number]
FROM ( SELECT [Filter1].[OrderID] AS [OrderID]
-- around 20 columns more
FROM ( SELECT [Extent1].[OrderID] AS [OrderID]
-- around 20 columns more
FROM [dbo].[Orders] AS [Extent1]
INNER JOIN -- small table
LEFT OUTER JOIN -- small table
LEFT OUTER JOIN -- small table
LEFT OUTER JOIN -- small table
LEFT OUTER JOIN -- small table
WHERE ([Extent1].[Status] IS NOT NULL)
AND (4 = CAST( [Extent1].[Status] AS int))
AND ([Extent1].[SomeDateTime] IS NULL)
AND ([Extent1].[Report] IS NULL)
) AS [Filter1]
OUTER APPLY (SELECT TOP (1) [Project1].[C1] AS [C1]
FROM ( SELECT CAST( [Extent7].[CreationDateTime] AS datetime2) AS [C1],
[Extent7].[CreationDateTime] AS [CreationDateTime]
FROM [dbo].[OtherTable] AS [Extent7]
WHERE [Filter1].[OrderID] = [Extent7].[OrderID]
) AS [Project1]
ORDER BY [Project1].[CreationDateTime] DESC
) AS [Limit1]
) AS [Project2]
) AS [Project2]
WHERE [Project2].[row_number] > 0
ORDER BY [Project2].[OrderID] ASC
它是由Entity Framework从LINQ到实体查询生成的。 查询发生在一些变体中,这些变体仅在第一个WHERE
子句中有所不同:
五个变种
WHERE ([Extent1].[Status] IS NOT NULL) AND (X = CAST( [Extent1].[Status] AS int))
X可以在0
到4
之间。 这些查询从来都不是问题。
这两个变种(*)
WHERE ([Extent1].[Status] IS NOT NULL) AND (4 = CAST( [Extent1].[Status] AS int)) AND ([Extent1].[SomeDateTime] IS NULL) AND ([Extent1].[Report] IS NULL)
或者... IS NOT NULL...
在最后一行。 我只有这两个查询才会遇到下面描述的问题。
“现象”是:
另外一个观察:
不知怎的,我怀疑整个问题与Express版本和varbinary(MAX)
列的内存限制(1 GB)有关,尽管我只是在WHERE
子句中使用它来检查列值是NULL
还是非NULL
。 “ Report
列本身不是所选列之一。
由于我正在运行明年Express版本的限制(10 GB mdf文件大小),我正在考虑更改:
Orders
表中 问题:查询突然变慢的原因是什么? 我计划的其中一项变更可以解决问题还是有其他解决方案?
编辑
在下面的评论中按照bhamby的提示,我在SSMS中设置了SET STATISTICS TIME ON
,然后再次运行查询。 当查询再次变慢时,我得到SQL Server parse and compile time
的高值,即: CPU time = 27,3 sec
, Elapsed time = 81,9 sec
。 查询的执行时间仅为CPU时间= 0,06秒,经过时间= 2,8秒。 在此之后第二次运行查询,为SQL Server解析和编译时间提供CPU时间0,06秒和经过时间= 0,08。
这看起来很浪费
SELECT TOP (1) [Project1].[C1] AS [C1]
FROM ( SELECT CAST( [Extent7].[CreationDateTime] AS datetime2) AS [C1],
[Extent7].[CreationDateTime] AS [CreationDateTime]
FROM [dbo].[OtherTable] AS [Extent7]
WHERE [Filter1].[OrderID] = [Extent7].[OrderID]
) AS [Project1]
ORDER BY [Project1].[CreationDateTime] DESC
是
SELECT max( CAST( [Extent7].[CreationDateTime] AS datetime2) ) AS [C1]
FROM [dbo].[OtherTable] AS [Extent7]
WHERE [Filter1].[OrderID] = [Extent7].[OrderID]
为什么不将日期存储为日期时间?
我不喜欢那种外在的申请
我会创建一个运行一次的#temp并加入它
确保并将[OrderID]声明为PK
SELECT [Extent7].[OrderID], max( CAST( [Extent7].[CreationDateTime] AS datetime2) ) AS [C1]
FROM [dbo].[OtherTable] AS [Extent7]
GROUP BY [Extent7].[OrderID]
你可以进行循环连接
接下来我会把它放在#temp2中,这样你就可以确定它只运行一次
再次确保将OrderID声明为PK
SELECT [Extent1].[OrderID] AS [OrderID]
-- around 20 columns more
FROM [dbo].[Orders] AS [Extent1]
INNER JOIN -- small table
LEFT OUTER JOIN -- small table
LEFT OUTER JOIN -- small table
LEFT OUTER JOIN -- small table
LEFT OUTER JOIN -- small table
WHERE ([Extent1].[Status] IS NOT NULL)
AND (4 = CAST( [Extent1].[Status] AS int))
AND ([Extent1].[SomeDateTime] IS NULL)
AND ([Extent1].[Report] IS NULL)
如果订单只有24,000行,那么你会有一些愚蠢的事情让你查询超过几秒钟。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.