如果所有值均为大写,是否需要大写索引?

时间:2018-08-29 19:54:21

标签: sql-server indexing

我有一个表ATable,其中有一个在ab上创建的索引。

我知道ab中的所有值都以大写形式存储。

我怀疑索引在这种情况下表现正常

select
    *
from
    BTable b 
join
    ATable a on upper(b.a) = a.a and upper(b.b) = a.b;

但是如果我做一个选择

会怎样?
select
    *
from
    BTable b 
join
    ATable a on upper(b.a) = upper(a.a) and upper(b.b) = upper(a.b);

将使用我的索引吗?还是我需要在ATable(upper(a), upper(b))上创建索引?


排序规则是:

select DATABASEPROPERTYEX('MyDB','Collation');
-----
SQL_Latin1_General_CP1_CI_AS

1 个答案:

答案 0 :(得分:2)

不,您不需要大写索引。

由于您使用的是不区分大小写的排序规则,因此查询中也不需要upper,并且正如Sean Lange所述,upper函数可以使该查询{{3} }(以下示例中没有)。如果删除upper并且在这些列上有索引,则可以使用它。我说可以,因为您正在做select *,所以优化器可以选择表扫描,因为您需要所有列。

为了进一步说明,由于排序规则不区分大小写,abcAbC相同,因此无论是否使用upper函数,都将返回相同的结果,但是性能之所以不一样,是因为:

  • upper函数本身需要时间和资源才能运行
  • 它会使查询成为非SARGable,这意味着您的索引可能不能被使用,从而损害性能

您可以通过选中nonSARGable来查看此操作。您会看到该功能很痛苦!

这是代码,以及该链接中的执行计划图片

create table #t1(c1 varchar(8) not null)
alter table #t1 add constraint t1_PK primary key (c1)

create table #t2(c1 varchar(8) not null)
alter table #t2 add constraint t2_PK primary key (c1)

insert into #t1
values
('aaa'),
('BBB'),
('ccc'),
('DDD')

insert into #t2
values
('AAA'),
('bbb'),
('Ccc'),
('dDD')

select *
from #t1 t1
inner join #t2 t2
on t1.c1 = t2.c1

select *
from #t1 t1
inner join #t2 t2
on upper(t1.c1) = upper(t2.c1)

drop table #t1
drop table #t2

out this query, with it's execution plan