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 。
查询优化器是否设法优先处理第一个子句,如果更简单的子句对于至少 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如果更简单的谓词返回一行,则该部分的阴影区域中的运算符不会被执行,但不能保证该计划。
| 归档时间: |
|
| 查看次数: |
1767 次 |
| 最近记录: |