如何使用Max函数使SQL语句更快

时间:2019-07-16 15:34:16

标签: sql

我有这个查询,但是它非常慢,并且将每个人都锁定在数据库之外,直到它解决了,我仍然可以加快它的速度。

SELECT Item.Barcode,
  Hetype.Description,
  Max(StockTakeDetails.xStockTake),
  Max(OpScans.ScanDate) AS Max_ScanDate
FROM Item
  INNER JOIN Hetype ON Item.Type = Hetype.Type
  LEFT JOIN StockTakeDetails ON StockTakeDetails.xItemID = Item.Itemref
  LEFT JOIN OpScans ON Item.Itemref = OpScans.xItemRef
WHERE Item.Lastservice = 1 AND
  Item.Deleted = FALSE AND
  Item.CommissionStatus <> 4
GROUP BY Item.Barcode,
  Hetype.Description 

2 个答案:

答案 0 :(得分:2)

我假设您正在使用SQL Server。如果没有,则此答案将不适用。

问题是您当前遇到读者阻止作者的情况。为了防止这种情况,您的数据库应配置为启用 multiversioning

这可以通过在SQL Server中打开“读取提交的快照隔离”来实现。

以下是有关此过程的不错的文章:Implementing Snapshot or Read Committed Snapshot Isolation in SQL Server: A Guide

Oracle数据库已经有数十年的多版本化(读者不会阻止作者,而作家也不会阻止读者),因此,Oracle开发人员通常会假设它在所有数据库中都相同,但是事实并非如此。 。 不过,SQL Server确实支持此功能,但默认情况下未启用该功能。

最后,您可以在紧急情况下使用一个非常粗糙的SQL Server技巧:将NOLOCK提示添加到查询中。从长远来看,这不是一个好主意,并且可能导致读取错误。不过,如果您的查询是针对未用于报告的摘要网页,则可能是这种廉价而愉悦的黑客手段的合理选择。 读取提交的快照隔离是更好的解决方案。

答案 1 :(得分:2)

您提供的信息很少,无法帮助您进行优化。您的问题没有数据库标签。它没有有关表或执行计划的大小信息。

但是,您似乎正在将一个表连接到两个不同的表,从而产生笛卡尔乘积。这可能是性能的根源。问题,所以我建议使用相关子查询重写查询:

SELECT i.Barcode, ht.Description,
       (SELECT MAX(std.xStockTake),
        FROM StockTakeDetails std
        WHERE std.xItemID = i.Itemref
       ),
       (SELECT MAX(os.ScanDate)
        FROM OpScans os
        WHERE os.xItemRef = i.Itemref
       ) AS Max_ScanDate
FROM Item i JOIN
     Hetype ht
     ON i.Type = ht.Type
WHERE i.Lastservice = 1 AND
      i.Deleted = FALSE AND
      i.CommissionStatus <> 4
GROUP BY i.Barcode, ht.Description ;

然后对于此查询,您需要以下索引:

  • Item(LastService, Deleted, CommissionStatus, Itemref)
  • HeType(Type, Description)
  • StockTakeDetails(xItemID, xStockTake)
  • OpScans(xItemID, ScanDate)

也许还有其他改进,但是我怀疑这将解决您的性能问题。