如果其他 where 子句返回足够多的结果,SQL Server 能否避免子查询或连接?

Ale*_*rin 4 sql-server optimization

以这个为例:

SELECT TOP 1 FROM customers
WHERE firstname LIKE 'John%'
   OR id IN (SELECT id_customer 
             FROM customer_emails 
             WHERE email like 'john.doe@%' )
Run Code Online (Sandbox Code Playgroud)

查询优化器是否设法优先处理第一个子句,如果更简单的子句对于至少 1 条记录(使用 Top 1)为真,则避免执行子查询?

我问这个主要是因为上面的查询可以重写为 Join,根据Join vs. sub-query从技术上讲,它会更快。但是,如果避免使用子查询,则在第一个子句可能为真的情况下,上面的示例显然优于 Join 。

Mar*_*ith 7

查询优化器是否设法优先处理第一个子句,如果更简单的子句对于至少 1 条记录为真,则避免执行子查询。

它可以做

create table customers(id int identity primary key, firstname varchar(10)) ;
insert into customers values ('John'),  ('Johnathan'), ('George');
create table customer_emails(id_customer int, email varchar(100));
insert into customer_emails values (1, 'John@example.com'),  (2, 'Johnathan@example.com');
Run Code Online (Sandbox Code Playgroud)

在计划中,我得到了与LIKE 'John%'谓词匹配的第一行,并且customer_emails根本没有执行扫描。

在此处输入图片说明

但是你的问题被表述为

如果更简单的子句至少有 1 条记录为真

这意味着更简单的 WHERE 子句会被整体评估,并且只有在失败时才会评估第二个。

为了

SELECT TOP 1 *
FROM customers
WHERE firstname LIKE 'George%'
   OR id IN (SELECT id_customer 
             FROM customer_emails 
             WHERE email like 'George.doe@%' );
Run Code Online (Sandbox Code Playgroud)

在发现匹配之前处理了三行,LIKE 'George%'随后进行了两次扫描customer_emails

重写如下...

create index ix on customers(firstname) include(id)

SELECT TOP 1 *
FROM customers with(forceseek)
WHERE firstname LIKE 'George%'
   OR  firstname NOT LIKE 'George%' AND  id IN (SELECT id_customer 
             FROM customer_emails 
             WHERE email like 'George.doe@%' );
Run Code Online (Sandbox Code Playgroud)

... 恰好给出了一个计划,IN如果更简单的谓词返回一行,则该部分的阴影区域中的运算符不会被执行,但不能保证该计划。

在此处输入图片说明