Sql-Server

為什麼此列有排序

  • January 14, 2022

此查詢有一個包含 SORT 的計劃,並且排序佔用了大部分 (77%) 成本:

SELECT
LFTYLM_STATUS
FROM
LFTYLM
WHERE
LFTYLM_LIS_ID = 138998 AND 
LFTYLM_LFTY_ID = 78 AND 
((LFTYLM_STATUS = 'A' AND (LFTYLM_DATE_INCLUDED_LAST IS NULL OR '1/1/2022' >= LFTYLM_DATE_INCLUDED_LAST)) OR (LFTYLM_STATUS = 'I' AND ('1/1/2022' >= LFTYLM_DATE_INCLUDED_LAST OR LFTYLM_DATE_INCLUDED_LAST IS NULL OR LFTYLM_DATE_INCLUDED_LAST < LFTYLM_DATE_UPDATED)))
ORDER BY
CASE WHEN (LFTYLM_STATUS = 'A') THEN 1 ELSE 2 END ASC,
CASE WHEN (LFTYLM_DATE_INCLUDED_LAST <= '1/1/2022') THEN DATEDIFF(DAY, '1/1/2022', CURRENT_TIMESTAMP) ELSE -9999 END DESC

該計劃位於: https ://www.brentozar.com/pastetheplan/?id=BktHa062K

為什麼 LFTYLM_STATUS 上有 SORT?

正在使用的索引包括 LFTYLM_STATUS 作為鍵列:

CREATE NONCLUSTERED INDEX [IX_LISTING_FEED_TYPE_LISTING_MAP_5] ON [dbo].[LISTING_FEED_TYPE_LISTING_MAP]
(
   LFTYLM_LIS_ID ASC,
   LFTYLM_LFTY_ID ASC,
   LFTYLM_DATE_INCLUDED_LAST ASC,
   LFTYLM_DATE_UPDATED ASC,
   LFTYLM_STATUS ASC
)
WITH (FILLFACTOR = 95)

即使有完美的索引,SQL Server也無法利用它們來避免對數據進行物理排序,就像 where 子句的編寫方式一樣。

這個問題在您的查詢計劃中很明顯,因為您不是按列排序,而是按表達式排序。

堅果

製作像這樣可索引的表達式的唯一方法是:

  • 製作計算列,並為它們編制索引
  • 創建索引視圖,並對結果列進行索引

否則,SQL Server 將不得不在執行時計算這些 case 表達式並對結果進行排序。

在旁邊

由於我看到您愛上了成本模因,因此我將在此處重複部分答案

我看到你經常談論成本,並降低成本。請不要關注成本。這是一個無單位的估計指標,與查詢的哪些部分緩慢且效率低下無關。

請注意,當您獲得實際執行計劃時,沒有“實際”成本。即使在 SQL Server 測量和報告許多其他執行時(實際)指標之後,它們仍然是估計值。

優化器使用成本快速選擇一個足夠好的計劃。減少它們不一定會讓您獲得更快的查詢。您可以有快速執行的昂貴查詢和執行緩慢的廉價查詢。

我建議查看操作員時間以確定哪些部分效率最低。

您有包含 LFTYLM_STATUS 和 LFTYLM_DATE_INCLUDED_LAST 的 ORDER BY 子句,因此對這兩列都進行了排序。

ORDER BY
CASE WHEN (LFTYLM_STATUS = 'A') THEN 1 ELSE 2 END ASC,
CASE WHEN (LFTYLM_DATE_INCLUDED_LAST <= '1/1/2022') THEN DATEDIFF(DAY, '1/1/2022', CURRENT_TIMESTAMP) ELSE -9999 END DESC

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