我正在查看其中兩個陳述句的執行計劃,并且對為什么該LEFT JOIN陳述句的性能優于該CROSS JOIN陳述句感到有些困惑:
表定義:
CREATE TABLE [Employee] (
[ID] int NOT NULL IDENTITY(1,1),
[FirstName] varchar(40) NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED ([ID] ASC)
);
CREATE TABLE [dbo].[Numbers] (
[N] INT IDENTITY (1, 1) NOT NULL,
CONSTRAINT [PK_Numbers] PRIMARY KEY CLUSTERED ([N] ASC)
); --The Numbers table contains numbers 0 to 100,000.
我為每位員工加入“一天”的問題中的查詢:
DECLARE @PeriodStart AS date = '2019-11-05';
DECLARE @PeriodEnd AS date = '2019-11-05';
SELECT E.FirstName, CD.ClockDate
FROM Employee E
CROSS JOIN (SELECT DATEADD(day, N.N, @PeriodStart) AS ClockDate
FROM Numbers N
WHERE N.N <= DATEDIFF(day, @PeriodStart, @PeriodEnd)
) CD
WHERE E.ID > 2000;
SELECT E.FirstName, CD.ClockDate
FROM Employee E
LEFT JOIN (SELECT DATEADD(day, N.N, @PeriodStart) AS ClockDate
FROM Numbers N
WHERE N.N <= DATEDIFF(day, @PeriodStart, @PeriodEnd)
) CD ON CD.ClockDate = CD.ClockDate
WHERE E.ID > 2000;
執行計劃:
如您所見,根據優化器,帶有看似冗余謂詞的第二個(左連接)查詢的成本似乎比第一個(交叉連接)查詢的成本低。當期間日期跨越多天時也是這種情況。
奇怪的是,如果我將 LEFT JOIN 的謂詞更改為不同的東西,就像1 = 1它會像 CROSS APPLY一樣執行。我還嘗試將 LEFT JOIN 的 SELECT 部分更改為SELECT N并加入CD.N = CD.N......但這似乎也表現不佳。
根據執行計劃,第二個查詢的索引查找僅從 Numbers 表中讀取 3000 行,而第一個查詢讀取了 10 倍。第二個查詢的索引查找也有這個謂詞(我假設它來自 LEFT JOIN):
dateadd(day,[Numbers].[N] as [N].[N],[@PeriodStart])=dateadd(day,[Numbers].[N] as [N].[N],[@PeriodStart])
我想了解為什么第二個查詢似乎表現得更好,即使我不會這樣做?這與我加入 DATEADD 函式的結果有關嗎?SQL 是否在加入之前評估 DATEADD 的結果?
uj5u.com熱心網友回復:
這些查詢得到不同估計的原因,即使計劃幾乎相同并且可能花費相同的時間,似乎是因為DATEADD(day, N.N, @PeriodStart)可空,因此CD.ClockDate = CD.ClockDate本質上只是驗證結果不為空。優化器看不到它總是非空的,因此降低了行估計值。
但在我看來,查詢中的主要性能問題是每次都選擇整個數字表。相反,您應該只選擇您需要的行數
SELECT E.FirstName, CD.ClockDate
FROM Employee E
CROSS JOIN (
SELECT TOP (DATEDIFF(day, @PeriodStart, @PeriodEnd) 1)
DATEADD(day, N.N, @PeriodStart) AS ClockDate
FROM Numbers N
ORDER BY N.N
) CD
WHERE E.ID > 2000;
使用此技術,您甚至可以CROSS APPLY (SELECT TOP (outerValue)在您想將行數與查詢的其余部分相關聯時使用。
有關數字表的更多提示,請參閱Itzik Ben-Gan 的優秀系列
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/374309.html
標籤:sql-server sql-server-2008 join
上一篇:MySQL合并兩個表并得到總和
