【问题标题】:Possible causes slow order by on sql server statementsql server 语句排序缓慢的可能原因
【发布时间】:2019-07-16 11:27:08
【问题描述】:

我有下一个查询,它返回 1550 行。

SELECT *
FROM V_InventoryMovements -- 2 seconds
ORDER BY V_InventoryMovements.TransDate -- 23 seconds

返回结果大约需要 2 秒。 但是当我包含 ORDER BY 子句时,大约需要 23 秒。 仅添加一个 ORDER BY 就是一个很大的变化。

我想知道发生了什么,以及使用 ORDER BY 改进查询的方法。退出 ORDER BY 不应该是解决方案。

这里有一些信息,如果您需要更多信息,请告诉我。

V_InventoryMovements

CREATE VIEW [dbo].[V_InventoryMovements]
AS
SELECT some_fields
FROM FinTime
RIGHT OUTER JOIN V_Outbound ON FinTime.StdDate = dbo.TruncateDate(V_Outbound.TransDate)
LEFT OUTER JOIN ReasonCode_Grouping ON dbo.V_Outbound.ReasonCode = dbo.ReasonCode_Grouping.ReasonCode
LEFT OUTER JOIN Items ON V_Outbound.ITEM = Items.Item
LEFT OUTER JOIN FinTime ON V_Outbound.EventDay = FinTime.StdDate

V_Outbound

CREATE VIEW [dbo].[V_Outbound]
AS
SELECT V_Outbound_WMS.*
FROM V_Outbound_WMS
UNION
SELECT V_Transactions_Calc.*
FROM V_Transactions_Calc

V_OutBound_WMS

CREATE VIEW [dbo].[V_OutBound_WMS]
AS
SELECT some_fields
FROM Transaction_Log
INNER JOIN MFL_StartDate ON Transaction_Log.TransDate >= MFL_StartDate.StartDate
LEFT OUTER JOIN Rack ON Transaction_Log.CHARGE = Rack.CHARGE AND Transaction_Log.CHARGE_LFD = Rack.CHARGE_LFD

V_Transactions_Calc

CREATE VIEW [dbo].[V_Transactions_Calc]
AS
SELECT some_fields
FROM Transactions_Calc
INNER JOIN MFL_StartDate ON dbo.Transactions_Calc.EventDay >= dbo.MFL_StartDate.StartDate

而且这里我也会分享一部分执行计划(可以看到主要成本的部分)。我不确切知道如何阅读它并改进查询。如果您需要查看执行计划的其余部分,请告诉我。但所有其他部分都是成本的 0%。主要成本在:嵌套循环(左外连接)成本 95%。

使用 ORDER BY 的执行计划

没有 ORDER BY 的执行计划

【问题讨论】:

  • 旁注:您是从另一个视图中的视图中选择吗?不要那样做,这对性能非常不利
  • 上传您的actual execution plans 并将链接添加到您的问题。 ORDER BY 可能会很昂贵,具体取决于查询的细节和可用索引。我在这里猜想带有ORDER BY 的排序运算符在有序列上,而没有它的排序在合并连接运算符的不同列上。合并连接通常对大量行更有效,但ORDER BY 可能会排除使用合并连接,并且总体上非常昂贵。
  • 正如@GuidoG 所说,嵌套视图不利于性能。它们看起来很合乎逻辑,但它们会削弱你的系统。请参阅格兰特弗里奇关于该主题的内容。 red-gate.com/simple-talk/sql/performance/…
  • @Dan Guzman,不错的链接,我不知道那个工具 ;-)
  • @Sean Lange,也感谢您的链接。非常有趣的信息。

标签: sql-server sql-order-by sqlperformance


【解决方案1】:

我认为简短的回答是优化器正在以不同的顺序执行以试图最小化排序成本,并且做得很差。正如 GuidoG 所建议的那样,视图中的视图中的视图使得它的工作变得非常困难。您可能能够通过创建一些额外的索引或统计信息来说服它以不同的方式执行,但是很难远程提供建议。

一种可能的解决方法是选择一个临时表,然后应用排序:

SELECT *
INTO #temp
FROM V_InventoryMovements; 

SELECT *
FROM #temp
ORDER BY TransDate

【讨论】:

  • 或者公用表表达式。
  • @James Casey 你明白了。我知道视图中的视图不是最好的,但有时(很多时候)你需要这样做,而且并不总是很痛苦(比如这种情况)。在任何情况下,您创建临时表的简单脚本都非常快。 SELECT INTO TempTable + SELECT FROM TempTable 大约需要 2 秒。惊人的! (但并不完美……SQL Server 需要这些棘手的步骤才能更快地工作?嗯……)
猜你喜欢
  • 1970-01-01
  • 2014-07-29
  • 2019-05-31
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-22
相关资源
最近更新 更多