SQL Server性能与左JOIN排序时



我有一个非常简单的查询,该查询需要长时间返回前20行。

SELECT    o.OrderId, 
          p.PaymentDate
FROM      dbo.Orders o                              -- 6 million records
LEFT JOIN dbo.Payments p ON p.OrderId = o.OrderId   -- 3.5 million records
WHERE     o.IsDeleted = 0                           -- There is an index on this column.
ORDER BY  p.PaymentDate DESC                        -- There is an index on this column and on OrderId
OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY

执行计划显示订单和付款表上的索引扫描,从订单中读取了600万行,从付款表中读取了300万行。

返回20行大约需要4-5秒。

如何使此查询返回结果更快?

您正在排序一个巨大的数据集,只是为了检索20行

如果这是一个典型的订单系统,那么ISDEATED = 0可能没有太大帮助,因为将删除订单的百分比?0.1%?排除它们对您要排序的订单数量

几乎没有影响

我也将付款状态标准放在那里,在那里也有稍微缩小记录的计数,以便对较小的集合进行分类。目前,您想要的逻辑是您想要20个记录,但是您不需要对600万张记录进行排序即可获得20个记录。将其剪切到20个记录。显然,这是一个忙碌的订购系统,每天至少要提交20个订单,因此您可能会发现只有一天以来仅使用Paymant Date选择记录,请从一天开始获得20个订单,但请选择很多天以给您20,甚至可能实施一些逻辑,如果您没有获得20次首次回合,那么您的前端应用程序会增加天数。您可以在前端缓存此回忆值,并随着天数的流逝而再次减少它,因此它成为自动派生的图

我认为您的另一个问题是您已经成为了左JON的,但是我看不到这样做的感觉 - 您是最近付费的订单,对吗?没有未付订单的付款记录?不管有600万订单付款的原因是什么,您似乎对没有付款记录的订单不感兴趣,所以我看不到让它成为左JON的感觉您绝对不想要的250万张唱片。使其成为内在的联接

您在付款日期之前进行排序 - 因此,您似乎需要匹配。因此,inner join就足够了。

此外,OrderId在付款表中。因此,您可以尝试此版本:

SELECT p.OrderId, p.PaymentDate
FROM dbo.Payments p
WHERE EXISTS (SELECT 1
              FROM dbo.Orders o
              WHERE p.OrderId = o.OrderId AND
                    o.IsDeleted = 0 
             )
ORDER BY p.PaymentDate DESC
OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY;

然后,对于此查询,您需要一个索引:

  • Payments(PaymentDate DESC, OrderId)
  • Orders(OrderId, IsDeleted)

最新更新