sql-server - 如果所有值都是大写,是否需要大写索引?
问题描述
我有一个在和ATable
上创建索引的表。a
b
我知道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
解决方案
不,您不需要大写索引。
由于您使用的是不区分大小写的排序规则,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
推荐阅读
- azure-cosmosdb-sqlapi - 是否可以在 Cosmos DB SQL 中为嵌套对象属性键使用参数
- typescript - 如何将推断参数连接到用于调用 TypeScript 函数的类型
- java - 角度无法识别对象类型
- python - 在 Python 中,如何在一行中从库中导入所有模块?
- java - 获取 Java JAR 资源文件夹中父目录的绝对 URL
- php - 使用 ajax 损坏的二进制下载
- flutter - Flutter - 如何为 TextField 的初始值提供来自 FutureBuilder 的动态值?
- python - discord.ext.commands.errors.CommandInvokeError:命令引发异常:AttributeError:'str'对象没有属性'name'
- electron - Electron.NET:自定义标题栏
- machine-learning - xgboost 回归树的叶值与预测有何关系