我遇到一个SQL数据库查询问题,该查询突然(但大约每三周一次)变慢。
安装程序如下:
Orders
)大约有24000条记录,其他五个连接的表很小(100条或更少的记录)Orders
的varbinary(MAX)
列Report
包含二进制数据(PDF文档),平均大小约为200至300 kB(但有时最多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-to-Entities查询生成的。该查询以几种变体形式出现,仅在第一个
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版本的内存限制(1 GB)和
varbinary(MAX)
列有关,尽管我只是在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解析和编译时间提供0,06 sec的CPU时间和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)
如果Order仅24,000行,那么愚蠢的事情将使您进行查询的时间超过几秒钟。
关于SQL Server查询突然变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17577960/