在SQL Server中为常用查询创建适当的索引

Sla*_*uma 7 sql database sql-server indexing sql-server-2008

在我的应用程序中,我有两个经常使用的查询.这些查询的Where子句如下:

WHERE FieldA = @P1 AND (FieldB = @P2 OR FieldC = @P2)
Run Code Online (Sandbox Code Playgroud)

WHERE FieldA = @P1 AND FieldB = @P2
Run Code Online (Sandbox Code Playgroud)

P1并且P2是在UI中输入或来自外部数据源的参数.

  • FieldA是一个int非常独特的,意味着:表中只有两个,三个,四个不同的值,比如20000行
  • FieldB是一个varchar(20)并且"几乎"是唯一的,FieldB可能只有很少的行可能具有相同的值
  • FieldC是一个varchar(15)非常独特的,但不如FieldB
  • FieldA和FieldB一起是唯一的(但不构成我的主键,这是一个带有聚簇索引的简单自动递增标识列)

我现在想知道定义索引以最好地加速这两个查询的最佳方法是什么.我应该用...定义一个索引

FieldB (or better FieldC here?)
FieldC (or better FieldB here?)
FieldA
Run Code Online (Sandbox Code Playgroud)

...或更好的两个指数:

FieldB
FieldA
Run Code Online (Sandbox Code Playgroud)

FieldC
FieldA
Run Code Online (Sandbox Code Playgroud)

还是有其他更好的选择吗?什么是最好的方式和原因?

提前感谢您的建议!

编辑:

正如其他读者的信息:这是另一个已被删除的答案.实际上答案对我来说似乎非常有用.建议是创建两个索引(根据我上面的第二个选项)并通过使用UNION两个select语句(一个带有WHERE FieldA = @P1 AND FieldB = @P2一个和一个带有WHERE FieldA = @P1 AND FieldC = @P2)来重新构造第一个查询,而不是OR从两个索引中受益(事实并非如此)使用OR运算符).

EDIT2:

使用OR并且未使用索引并且UNION更可取的声明似乎是错误的 - 至少根据我自己的测试(参见下面我自己的答案).

gbn*_*gbn 3

扩展莱姆斯的(编辑:现已删除)答案......

  • 如果 @p2 是 varchar(15) 那么你无法可靠地与 FieldB 进行比较,它是 varchar(20)
  • 如果 @p2 是 varchar(20) 那么 FieldC 将转换为 varchar(20) 并且不使用索引(或者最多扫描它)
  • 如果 @p1 只有 2、3、4 个值,那么为什么不使用tinyint 并减少表/索引的大小呢?

在解决此数据类型优先级问题之前,我不会理会索引:这是 OR 子句问题的顶部。

最后,一列是唯一的还是非唯一的:没有中间的情况。统计数据有助于提高选择性,但无关紧要。

由于 FieldA 的选择性,我会将 Remus 答案中的索引反转为FieldB, FieldA(并且是唯一的)FieldC, FieldA

编辑,评论后:您无法将 @p2 的使用与常量字符串的使用进行比较。