允许null的ORDER BY列很慢。为什么?

时间:2011-04-20 21:22:20

标签: sql sql-server performance tsql

所以我的问题确实是为什么

无论如何,我有这个查询做了一些内连接,有一个where子句并在nvarchar列上执行一个order。如果我运行查询WITHOUT order by,查询只需不到一秒钟。如果我按顺序运行查询,则需要12秒。

现在我有一个好主意,并将所有INNER JOIN更改为LEFT JOIN。并且还包括ORDER BY子句。这花了不到一秒钟。所以我记得LEFT JOIN和INNER JOIN之间的区别。 INNER JOIN检查NULL,而LEFT JOIN则不检查。所以我进入桌面设计并取消选中“Allow Nulls”。现在我运行查询WITH INNER JOINs和ORDER BY子句,查询只需不到一秒钟。 为什么?

根据我的理解,FROM,JOINS,WHERE,然后SELECT子句应首先运行并返回结果集。然后ORDER BY子句在结果记录集的最后运行。因此,查询应该已经 AT MOST 一秒,是的,即使列允许空值。那么为什么查询在没有order by子句的情况下需要不到一秒的时间,但是使用order by子句需要12秒?这对我来说没有意义。

以下查询:

SELECT PlanInfo.PlanId, PlanName, COALESCE(tResponsible, '') AS tResponsible, Processor, CustName, TaskCategoryId, MapId, tEnd,
CASE MapId WHEN 9 THEN 1 ELSE 2 END AS sor
FROM PlanInfo INNER JOIN [orders].dbo.BaanOrders_Ext ON PlanInfo.PlanName = [orders].dbo.BaanOrders_Ext.OrderNo
INNER JOIN [orders].dbo.BaanOrders ON PlanInfo.PlanName = [orders].dbo.BaanOrders.OrderNo
INNER JOIN Tasks ON PlanInfo.PlanId = Tasks.PlanId
INNER JOIN EngSchedToTimingMap ON Tasks.CatId = EngSchedToTimingMap.TaskCategoryId
WHERE (MapId = 9 OR MapId = 11 or MapId = 13 or MapId = 15)
AND([orders].dbo.BaanOrders_Ext.Processor = 'metest' OR tResponsible = 'metest')
ORDER BY PlanInfo.PlanId

3 个答案:

答案 0 :(得分:2)

使用ORDER BY子句时,强制数据库引擎对结果进行排序。这需要一些时间(特别是如果结果包含许多行) - 因此,在没有ORDER BY子句的情况下运行1秒的查询可能会运行12秒。请注意,排序最多需要O(N * log(N))时间,其中N是行数。

NULL通常很慢的原因是它们必须经过特殊处理。使用NULL排序会增加更复杂的比较条件,并减慢排序速度。

答案 1 :(得分:2)

我不得不猜测,这是因为你在排序的PlanInfo.PlanId上有一个索引。

SQL Server可以简化集合,使其跟随索引并按顺序构建其余列。当该字段为NULLable时,索引不能用于排序,因为它不包含偶然出现的NULL值,因此它决定沿着不同的路径进行优化。

显示执行计划总是有帮助的。粘贴计划的图像,或只显示文本模式计划,即添加查询上方的行,然后执行它

SET SHOWPLAN_TEXT ON;
<the query>

答案 2 :(得分:0)

如果您的问题是“为什么ORDER BY子句导致我的查询运行时间更长?”答案是因为对结果进行排序会添加到查询执行计划中。

如果您使用SQL Server Studio中的“显示估计的查询执行计划”工具,它将准确显示它认为SQL Server引擎将执行的操作。