Sql-Server-2014

對於擁有 max(),我們還有哪些其他選擇?

  • April 14, 2022

我刪除了我的舊問題,以便更準確地了解我需要什麼。

我們有一個包含許多較小查詢的大查詢。這個查詢執行得非常好,直到它到達“having max”子句:

having 
 max
 (
   DateField 
   ) < getdate() - @2_years_ago

有沒有比擁有 max 更快的條款?因為這會導致索引掃描以及表中存在的數百萬行不停地循環和循環。

我試圖按 row_number 做,但沒有運氣。

我只是注意到這個相同的查詢在具有相同結構的其他數據庫上執行得很好。

只是這個(有趣的是行更少)它不起作用。

數據庫在同一台伺服器上。

您的主要問題似乎是基數估計不佳導致編譯器重新排序連接。當您使用 時,這似乎發生得更多OPTION (RECOMPILE),因為伺服器正在做出不同的估計。

您應該能夠足夠簡化您目前的查詢,以便編譯器會發現它更容易

如果沒有看到您的架構,很難準確地說出,但似乎您可以將EXISTS邏輯翻轉到NOT EXISTS.

  • 您的原件說“確保組中的最大日期小於我的日期”
  • 您實際上希望組中不應該有小於日期的行,因此您可以說“確保沒有日期超過我的日期的行”。
  • 您現在不需要 aHAVING來查找最大日期。

您現有的查詢有很多問題:

  • a b c是愚蠢的別名,考慮使用更有意義的別名。
  • 用於[]引用列名,而不是''. 除非必須,否則不要引用。
  • 為什麼NOLOCK像五彩紙屑一樣四處飛濺,你希望用它來達到什麼目的?它對數據完整性有非常嚴重的影響。考慮改用TABLOCK提示或SNAPSHOT隔離。
  • 左連接表正在被過濾,所以你有一個隱式內連接,你應該只使用內連接。
  • EXISTS子查詢不需要選擇任何東西,實際上它被忽略了。你可以這樣做EXISTS (SELECT 1
  • 為什麼三個子查詢,看起來你應該能夠做到這一點。
  • where b.[MerchantLogId] = a.[MerchantLogId] group by b.[MerchantLogId]沒有意義:您將始終只有一組,因此不需要group by.
  • 似乎您不需要NTFM_MerchantLog子查詢,因為它是由主鍵連接的。
  • 不要在日期上使用算術,它效果不好。而是使用DATEADD

似乎您也可以通過連接所有表並使用OR(為此您仍然需要一些左連接)將三個子查詢合併為一個。

希望在進行所有這些改進之後,您應該會看到更好的性能

SELECT
 'NTFM_MerchantLog' AS [Process Master],
 COUNT(DISTINCT ml.MerchantLogId) AS [Registers Count]
FROM
 dbo.NTFM_MerchantLog ml
 JOIN dbo.v_ntfm_merchantlogstatus mls on mls.MerchantLogStatusId = ml.StatusId
WHERE
 ml.CreateDate < @Today - @lv_2484deletionCycle
 AND mls.Status IN ('Closed', 'Expired', 'Reconciled') 

 AND NOT EXISTS (SELECT 1
   FROM dbo.ntfm_merchantlogtransactions mlt
   JOIN dbo.accounttransaction at1 ON at1.accountTransactionId = mlt.accountTransactionId

   LEFT JOIN (
       dbo.ntfm_merchantlogtransactions mlt2
       JOIN dbo.ntfm_merchantlog ml2 ON ml2.MerchantLogId = mlt2.MerchantLogId

       LEFT JOIN (
           dbo.ntfm_merchantlogtransactions mlt3
           JOIN dbo.accounttransaction at2 on at2.accountTransactionId = mlt3.accountTransactionId
       ) ON mlt3.MerchantLogId = ml2.MerchantLogId
   ) ON mlt2.accountTransactionId = at1.accountTransactionId

    WHERE
      mlt.MerchantLogId = ml.MerchantLogId
    AND (
          at1.postingdt  >= DATEADD(day, -@lv_2484deletionCycle, @Today)
       OR ml2.createdate >= DATEADD(day, -@lv_2484deletionCycle, @Today)
       OR at2.postingdt  >= DATEADD(day, -@lv_2484deletionCycle, @Today)
    )
 );

引用自:https://dba.stackexchange.com/questions/310862