MySQL 系列文章---使用 EXISTS 优化子查询

某些优化适用于使用IN(或=ANY)来测试子查询结果的比较,特别是关于NULL带来的。讨论的最后一部分建议如何优化。

以下两个表数据基本一致都在一万左右

考虑以下子查询比较:

SELECT
	* 
FROM
	retired_cadre_base 
WHERE
	cardre_id IN (
	SELECT
		cardre_id 
	FROM
		retired_cadre_family 
	WHERE
	post_code = '317000')

MySQL“从外到内”执行查询。也就是说,它首先获取外部表达式的值,然后运行子查询并获取它产生的行。

这里的优化可以是赋连接条件于子查询,只有内部表达式inner_expr等于outer_expr的行才是所关注的。这是通过向子查询的WHERE子句下推一个适当的相等项来实现的,限制查询范围。转换后的SQL语句如下所示:

SELECT
	* 
FROM
	retired_cadre_base a 
WHERE
	EXISTS (
	SELECT
		1 
	FROM
		retired_cadre_family b 
	WHERE
	post_code = '317000' 
	AND a.cardre_id = b.cardre_id)

转换之后,MySQL就能够使用下推而来的等式去限制行的数量,即在计算子查询时必须使用该等式进行检查。

更一般地说,将N个值与返回N个行值的子查询进行比较时,也需要进行同样的转换。如果oe_i和ie_i分别代表外部和内部表达式的值,则子查询比较的示例如下:

(oe_1, ..., oe_N) IN
  (SELECT ie_1, ..., ie_N FROM ... WHERE subquery_where)

变成:

EXISTS (SELECT 1 FROM ... WHERE subquery_where
                          AND oe_1 = ie_1
                          AND ...
                          AND oe_N = ie_N)

为了简单起见,下面的讨论假释使用的是一对外部表达式和内部表达式的值。

如果以下任何一个条件为真,则上述讨论过的“下推”策略也有效:

outer_expr和inner_expr都不能为NULL。

如果该子查询是WHERE子句中的OR或AND的组成部分,则MySQL假设你不会在意。因此你不必区分子查询结果是NULL还是FALSE。优化器注意到另一种不必区分子查询结果是NULL或FALSE的实例,请看如下构建的条件:

... WHERE outer_expr IN (subquery)

在这种情况下,WHERE子子句都会拒绝不管IN (subquery)返回NULL还是FALSE时的行。

假设已知outer_expr的值是非空的,但是,子查询不能产生符合outer_expr = inner_expr的行。那么,outer_expr IN (SELECT inner_expr …)计算结果如下:

如果SELECT产生的任何行的条件是inner_expr是NULL,那么以上表达式计算结果是NULL

如果SELECT产生的只有非空值或什么也没有产生,那么以上表达式计算结果是FALSE

在这种情况下,寻找符合outer_expr = inner_expr的方法已无效。虽然寻找这样的行是必要的,但是如果找不到,那么也要寻找符合inner_expr is NULL的行。粗略地说,该子查询可以被转换成以下形式:

EXISTS (SELECT 1 FROM .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NoLongerConfused

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值