【问题标题】:Convert to SARGable query转换为 SARGable 查询
【发布时间】:2019-05-20 21:32:54
【问题描述】:

我想写一个查询来搜索表中包含的字符串。

表:

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

实际执行计划:

如何强制查询处理器在大型数据集上使用索引查找而不是表/索引扫描?

【问题讨论】:

  • 这些查询都不是 SARGable,因为前导通配符意味着“正常”索引是无用的。 (n)(var)char 数据类型上的索引按从左到右的排序顺序对字母进行排序。如果您正在查找在值中的任何位置包含字符串'ee' 的值,那么没有排序将帮助您。如果您需要执行这样的查询,则需要考虑全文索引。
  • 除了全文索引还有其他选项吗?
  • 如果您要搜索的只是'%ee%',则创建一个持久计算列。否则,您唯一的其他选择就是每次要进行领先的通配符搜索时都进行一次表扫描。

标签: tsql indexing sql-server-2008-r2 query-performance


【解决方案1】:

根据定义,您发布的所有查询都不是 SARgable,例如,使用 '%..%'' 会自动强制查询引擎进行扫描,另一种情况是使用函数(如charindex 或 patindex)在谓词内的列中。

这里有一些帖子:https://bertwagner.com/2017/08/22/how-to-search-and-destroy-non-sargable-queries-on-your-server/

如果你必须使用通配符执行这种查询,Kimberly Tripp 写了非常有趣的文章,也许值得检查一下使用 FullTextSearch 功能的可能性。我的观点是,或者你的限制并在你的查询中做一个精确的谓词,否则你将不得不改变策略,几乎忘记了,不要试图强制使用带有 HINT 的 Seek,我看不出这种药会比疾病好。

【讨论】:

    【解决方案2】:

    搜索参数,简称 SARG,是一个过滤谓词,它使优化器能够依赖 索引顺序。过滤谓词使用以下形式(或具有两个分隔符的变体 范围,或翻转操作数位置): 在哪里<column> <operator> <expression>

    这样的过滤器是sargable如果:

    1. 您不会对过滤后的列应用操作。

    2. 该运算符标识索引中连续范围的合格行。那是 运算符的大小写,如 =、>、>=、、LIKE 这样的以通配符为前缀的运算符,情况并非如此。

    在大多数情况下,当您对过滤后的列应用操作时,优化器不会 尝试太聪明,理解计算的含义,如果索引排序 仍然可以依靠。它只是假设结果值的排序可能与 源值,因此不能信任索引排序。

    那么,为什么 SQL Server 不将索引用于 %ee% 查询呢?假装你手里拿着一本电话簿,我让你找到姓氏中包含字母 %ee% 的每个人。您必须扫描电话簿中的每一页,因为结果将包括以下内容:

    • 安妮·李

    • 李勇

    • 凯瑟琳

    • 艾琳

      当我向您询问姓名中任何位置包含 %ee% 的所有姓氏时,我的查询不是 sargable - 这意味着您无法利用索引进行索引查找。

    这就是 SQL Server 的全文搜索的用武之地。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-17
      • 2014-11-16
      • 2019-07-29
      相关资源
      最近更新 更多