同一列的多个筛选索引

时间:2017-06-18 10:15:35

标签: sql sql-server

根据相同列的不同条件创建多个筛选索引是否有意义?例如,假设如下:

 CREATE TABLE [dbo].[Skills](
     [UserId] INT NOT NULL PRIMARY KEY,
     [SkillTitle] NVARCHAR(50) NOT NULL,
     [SkillLevel] INT NOT NULL CHECK ([SkillLevel] BETWEEN 0 AND 10)
 ) 
 GO

 CREATE INDEX [IX_Skill_Low] ON [dbo].[Skill] (SkillTitle,SkillLevel) WHERE SkillLevel BETWEEN 3 AND 0
 GO

 CREATE INDEX [IX_Skill_Moderate] ON [dbo].[Skill] (SkillTitle,SkillLevel) WHERE SkillLevel BETWEEN 5 AND 3
 GO

 CREATE INDEX [IX_Skill_Good] ON [dbo].[Skill] (SkillTitle,SkillLevel) WHERE SkillLevel BETWEEN 7 AND 5
 GO

 CREATE INDEX [IX_Skill_High] ON [dbo].[Skill] (SkillTitle,SkillLevel) WHERE SkillLevel > 7

或者创建一个非过滤索引会更好吗?

如果进行以下查询SELECT * FROM Skills WHERE SkillLevel BETWEEN 7 AND 1会发生什么?

1 个答案:

答案 0 :(得分:2)

除非每个技能等级变化都有数百万条记录。

即,
在5和3之间 在5和7之间

我不建议这样做,我建议创建一个单独的过滤索引,如下所示

skilllevel between 1 and 10
  

如果进行以下查询会发生什么SELECT * FROM Skills WHERE SkillLevel BETWEEN 7 AND 1?

如果你的select *包含许多列,而不是索引中没有指定的列,则sql可能

  • 选择使用此索引,并在基表上查找其余列
  • 进行全表扫描

我会创建一个以下覆盖索引,但这取决于您的数据

create index nci_test on table(skilllevel)
include(SkillTitle)

我做了一些测试以了解更多,你可以在下面找到测试脚本

CREATE TABLE [dbo].[Skills](
     [UserId] INT NOT NULL  identity(1,1) PRIMARY KEY,
     [SkillTitle] NVARCHAR(50) NOT NULL,
     [SkillLevel] INT NOT NULL CHECK ([SkillLevel] BETWEEN 0 AND 10)
 ) 
 GO

insert into dbo.Skills
(SkillTitle,SkillLevel)
select cast(NEWID() as varchar(50)),
case when rand()*10<0 then 1 else rand()*10 end
go 100000

现在让我们运行一些查询

create index nci_1and5 on dbo.skills(skilllevel)
include(skilltitle)
where skilllevel >= 1 and skilllevel <=5

create index nci_5and10 on dbo.skills(skilllevel)
include(skilltitle)
where skilllevel >5 and skilllevel <=10

select * from skills where skilllevel 
between 1 and 4--uses 1 to 5 index

select * from skills where skilllevel 
between 6 and 10--uses 6 to 10 index

select * from skills where skilllevel 
between 1 and 7--uses scan

然而,即使你在技能水平之间有数百万行,我也不推荐这些指数。我会建议分配