我想知道是否有人可以闡明爲什麼SQL Server(2016 RTM在我的情況下,但我懷疑這不是版本特定的)執行這個看似不必要的INNER JOIN。SQL Server查詢優化器執行不必要的連接
考慮外鍵加入了以下兩個表:
CREATE TABLE [dbo].[batches](
[Id] [smallint] IDENTITY(1,1) PRIMARY KEY,
[Date] [date] NOT NULL,
[Run] [tinyint] NOT NULL,
[Clean] [bit] NOT NULL)
CREATE TABLE [dbo].[batch_values](
[Batch_Id] [smallint] NOT NULL,
[Key] [int] NOT NULL,
[Value] [int] NOT NULL,
CONSTRAINT [PK_batch_values] PRIMARY KEY CLUSTERED
([Batch_Id] ASC, [Key] ASC))
GO
ALTER TABLE [dbo].[batch_values] WITH CHECK
ADD CONSTRAINT [FK_batch_values_batches] FOREIGN KEY([Batch_Id])
REFERENCES [dbo].[batches] ([Id])
GO
ALTER TABLE [dbo].[batch_values] CHECK CONSTRAINT [FK_batch_values_batches]
GO
填充表的一些數據:現在
SET NOCOUNT ON;
DECLARE
@BatchCount int,
@BatchId smallint,
@KeyCount int;
SET @BatchCount = 1;
WHILE @BatchCount <= 100
BEGIN
INSERT INTO dbo.[batches]
VALUES (DATEADD(dd, @BatchCount/10, '2016-01-01'), @BatchCount % 10, @BatchCount % 2);
SET @BatchId = SCOPE_IDENTITY();
SET @KeyCount = 1;
WHILE @KeyCount <= 1000
BEGIN
INSERT INTO dbo.batch_values
VALUES (@BatchId, @KeyCount, RAND() * 1000000 - 500000);
SET @KeyCount = @KeyCount + 1;
END;
SET @BatchCount = @BatchCount + 1;
END;
,如果我運行下面的查詢執行計劃顯示即使沒有從中選擇列,SQL Server也正在對[批處理]表執行INNER JOIN,並且由於外鍵約束的原因,由於連接而無法從[批處理值]中刪除記錄。
screenshot of query and execution plan
這在我看來,查詢優化器應該丟棄INNER JOIN是不必要的,只是做一個主鍵徵求[batch_values],但事實並非如此。
這是很重要的,因爲如果我開發視圖連接多個表來呈現底層數據的「更大圖片」以便於使用,那麼在查詢這些視圖時,我將會獲得性能優勢。
行不能丟棄,但它們可以相乘。 – Blorgbeard
哦,不,他們不能,因爲你在batch_values上指定了PK。嗯。 – Blorgbeard
哦,是的,他們可以這樣做,因爲FK只能用一種方式。它可能會從其他表中遺漏。這是一個奇怪的情況,因爲它是一個垂直分區表(都加入主鍵)。如果我以正確的方式讀取FK,您可以在'batch'中創建一條記錄,而不會以'batch_values'存在(但不是另一種方式) –