我有兩張桌子
[dbo].[Employee](
[EmployeeID] [int] IDENTITY(1,1) NOT NULL,
[Title] [varchar](50) NULL,
[Role] [int] NULL,
[Status] [varchar](1) NULL)
[dbo].[Roles](
[id] [int] IDENTITY(1,1) NOT NULL,
[Role] [varchar](25) NULL,
[Description] [varchar](25) NULL)
通過 id 使用主集群鍵。我也有存盤程序
SELECT
[EmployeeID]
,[Title]
,employee.[Role]
,roles.Role AS RoleName
FROM [dbo].Employee AS employee
INNER JOIN [dbo].Roles AS roles ON roles.id = employee.Role
WHERE [Status] <> 'D'
執行計劃向我展示了我想避免的“聚集索引掃描”。有什么方法可以將其轉換為“聚集索引搜索”? 執行計劃螢屏
<資料庫小提琴>
uj5u.com熱心網友回復:
正如我在評論中提到的,CLUSTERED INDEXondbo.Employees不會在這里幫助你。這樣做的原因是因為您正在篩選列status,該列僅包含在 中CLUSTERED INDEX,但并未對其進行排序。結果,RDBMS別無選擇,只能掃描整個表以過濾掉Status值為的行D。
您可以INDEX在列Status和INCLUDE其他列上添加一個,這可能會導致索引查找(而不是聚集索引查找),但是,由于您使用<> D然后 RDBMS 可能會感覺仍然選擇執行掃描;是否確實取決于您的資料分布:
CREATE INDEX IX_EmployeeStatus ON dbo.Employee (Status) INCLUDE (Title, Role);
還要FOREIGN KEY在您的表中添加一個:
ALTER TABLE dbo.Employee ADD CONSTRAINT FK_EmployeeRole FOREIGN KEY (Role) REFERENCES dbo.Roles (id);
資料庫<>小提琴
uj5u.com熱心網友回復:
如果您在 Status 列上有一個索引,那么該代碼應該會導致兩個索引搜索。一個用于<'D',一個用于>'D'。你只需要一個關于狀態的索引。
您可以使用臨時表將其轉換為一次搜索,將“Not”轉換為“is”,這在查詢優化中始終是一個好主意:
CREATE TABLE #StatusMatch (StatusCode varchar(1) NOT NULL PRIMARY KEY CLUSTERED)
INSERT INTO #StatusMatch WITH(TABLOCKX)
SELECT Status
FROM dbo.Employee WITH(NOLOCK)
WHERE Status <> 'D'
GROUP BY Status
ORDER BY Status;
SELECT a.EmployeeID, a.Title, a.Role, b.Description AS RoleName
FROM dbo.Employee a WITH(NOLOCK)
INNER JOIN dbo.Roles b WITH(NOLOCK) ON a.Role = b.id
INNER JOIN #StatusMatch c ON a.Status = c.StatusCode
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/403156.html
標籤:
