如何使用LIKE语句强制查询合理的执行计划?

时间:2018-04-02 13:34:33

标签: sql-server

在创建即席查询以查找表中的信息时,我一遍又一遍地遇到此问题。

假设我有一个包含百万条记录的表,其中包含字段id - int,createddatetime - timestamp,category - varchar(50)和content - varchar(max)。我想查找最后一天在内容字段中有特定字符串的所有记录。如果我创建这样的查询......

select *
from table
where createddatetime > '2018-1-31'
    and content like '%something%'

它可能会在一秒内完成,因为在最后一天可能只有100条记录,所以LIKE子句只在少数记录上运行

但是如果我在where子句中添加一个项目......

select *
from table
where createddatetime > '2018-1-31'
    and content like '%something%'
    and category = 'testing'

然后锁定表格可能需要几分钟才能完成。

它似乎正在从首先执行所有直接WHERE子句项,然后在有限的记录集上执行LIKE,而不是首先使用LIKE子句。甚至有时候会有多个LIKE语句,并且添加一个LIKE语句会导致查询从一秒钟到几分钟。

我发现的唯一解决方案是生成一个中间表(可能临时表可以工作),根据基本的WHERE子句项插入记录,然后运行一个单独的查询来过滤一个或多个LIKE语句。我尝试了各种JOIN和CTE方法,这些方法通常都没有改进。或者,如果尝试转换多个LIKE语句的逻辑,CHARINDEX似乎也很难使用。

是否有任何提示或某些东西可以放在查询语句中,告诉sql server等待记录被基本WHERE子句项过滤后再过滤LIKE?

我实际上只是试过这种方法而且它有同样的问题...

select *
from (
    select *, charindex('something', content) as found
    from bounce
    where createddatetime > '2018-1-31'
) t
where found > 0

当子查询在几秒钟内独立返回时,整个查询永远不会返回。为什么这么糟糕

1 个答案:

答案 0 :(得分:1)

不是很花哨,但我对临时表的好运比嵌套的select语句更好......它会隔离第一个数据集,然后你可以从中选择。如果您正在寻找快速和肮脏的,这通常可以满足我的目的,这可能有所帮助。如果这是一个永久存储过程,从长远来看,索引建议可能会为您提供更好的服务。

select *
into #like
from table
where createddatetime > '2018-1-31'
    and content like '%something%'

select * 
from #like 
where category = 'testing'