I have two tables
[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)
with primary clustered keys by id. Also I have stored procedure
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'
The Execution plan shows me a ‘Clustered Index Scan’ that I want to avoid. Is there any way I can convert it to a ‘Clustered Index Seek’? Execution Plan screen
Advertisement
Answer
As I mentioned in the comments, the CLUSTERED INDEX
on dbo.Employees
isn’t going to help you here. The reason for this is because you are filtering on the column status
, which is simply included in the CLUSTERED INDEX
, but isn’t ordered on it. As a result, the RDBMS has no option but to scan the entire table to filter out the rows where Status
has a value of D
.
You could add an INDEX
on the column Status
and INCLUDE
the other columns, which may result in an index seek (not a clustered index seek), however, due to you using <> D
then the RDBMS may feel still chose to perform a scan; whether it does depends on your data’s distribution:
CREATE INDEX IX_EmployeeStatus ON dbo.Employee (Status) INCLUDE (Title, Role);
Also add a FOREIGN KEY
to your table:
ALTER TABLE dbo.Employee ADD CONSTRAINT FK_EmployeeRole FOREIGN KEY (Role) REFERENCES dbo.Roles (id);