首页 > 解决方案 > 如果所有值都是大写,是否需要大写索引?

问题描述

我有一个在和ATable上创建索引的表。ab

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

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

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

标签: sql-serverindexing

解决方案


不,您不需要大写索引。

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

更详细地说,由于排序规则不区分大小写,因此与abc相同AbC,因此无论是否使用您的函数,都会返回相同的结果,upper但性能不会相同,因为:

  • upper函数本身需要时间和资源来运行
  • 它可以使查询 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

执行计划


推荐阅读