我想编写查询来搜索表中包含的字符串。
表格:
Create table tbl_sarg
(
colname varchar(100),
coladdres varchar(500)
);
注意:我只想使用Index Seek
来搜索3亿条记录。
索引:
create nonclustered index ncidx_colname on tbl_sarg(colname);
样本记录:
insert into tbl_sarg values('John A Mak','HNo 102 Street Road Uk');
insert into tbl_sarg values('Shawn A Meben','Church road USA');
insert into tbl_sarg values('Lee Decose','ShopNo 22 K Mark UK');
insert into tbl_sarg values('James Don','A Mall, 90 feet road UAE');
查询1:
select * from tbl_sarg
where colname like '%ee%'
实际执行计划:
查询2:
select * from tbl_sarg
where charindex('ee',colname)>0
实际执行计划:
查询3:
select * from tbl_sarg
where patindex('%ee%',colname)>0
实际执行计划:
如何强制查询处理器对大型数据集使用索引查找代替表/索引扫描?
答案 0 :(得分:1)
根据定义,您发布的所有查询都不是可SARg的,例如,使用'%..%'会自动强制查询引擎执行扫描,另一种情况是使用函数(例如charindex或patindex)在谓词中的列中。
这里有一些帖子:https://bertwagner.com/2017/08/22/how-to-search-and-destroy-non-sargable-queries-on-your-server/
如果您必须使用通配符执行这种查询,金伯利·特里普(Kimberly Tripp)撰写了很多有趣的文章,也许值得检查一下使用FullTextSearch功能的可能性。我的意思是,或者您要限制并在查询中做一个精确的谓词,否则您将不得不改变策略,几乎忘记了,不要试图将Seek与HINT一起使用,我看不出这种药会比疾病好。
答案 1 :(得分:1)
搜索参数(简称SARG)是一个过滤谓词,可让优化程序依赖
索引顺序。过滤谓词使用以下形式(或带有两个定界符的变体
范围,或操作数位置翻转):
<column> <operator> <expression>
如果满足以下条件,则此过滤器可设置:
您不要对已过滤的列进行操作。
运算符在索引中标识连续范围的合格行。那是 运算符,例如=,>,> =,<,<=,BETWEEN,具有已知前缀的LIKE等。 像<>,以通配符作为前缀的LIKE这样的运算符不是这种情况。
在大多数情况下,将操作应用于过滤后的列时,优化器不会 尝试太聪明,理解计算的含义,以及是否对索引进行排序 仍然可以依靠。它只是假设结果值的排序方式可能与 源值,因此不能信任索引顺序。
那么SQL Server为什么不将索引用于%ee%
查询?假装您手里拿着电话簿,我要求您查找姓氏包含字母%ee%的所有人。您将必须扫描电话簿中的每个页面,因为结果将包括以下内容:
李安妮(Anne Lee)
李容
凯瑟琳
Alien
当我要求您提供名称中任何位置包含%ee%
的所有姓氏时,我的查询都不可靠-这意味着您无法利用索引进行索引查找。
这就是 SQL Server全文搜索的地方。