[英]Mysql optimize subquery in where clause
如果我执行查询,例如
SELECT *
FROM `table1`
WHERE 1 OR EXISTS (
SELECT show
FROM `table2`
WHERE id IN(1,2,3)
)
我希望优化器能够意识到 where 子句总是解析为 true,因此没有必要运行子查询。 使用 EXPLAIN 运行查询表明情况并非如此,无论如何都会执行子查询。 这是一个更复杂问题的缩小示例,我尝试根据外部查询的列值执行不同的子查询,例如:
SELECT value FROM table t
LEFT JOIN...
WHERE
(SELECT
IF(t.value = 1,
(SELECT ...),
(SELECT ...)
)
)
其含义是只执行 where 条件中的一个内部子查询,但这里也发生了同样的情况,两者都被执行,但只使用了一个的值。 所以结果是正确的,但运行了无用的查询。 我已经尝试过 CASE WHEN 以及同样的问题。 不确定是因为我使用 MariaDB 还是我在这里遗漏的东西。
对不起,我希望我能正确理解你的问题。 在WHERE 1的第一个查询中,MySQL 永远不会执行 EXISTS 子查询。 EPLAIN 只向您展示可以做什么。 你可以通过SHOW status LIKE 'Handler_read_first'看到它很简单; 我有2张桌子。 如果我用 WHERE 1 进行测试,它的唯一增量为 1(读取 1 个表),而没有它的增量为 2
样本
桌子
MariaDB [test]> select * from index_usage;
+----+------+------+------+-------+
| id | a | b | c | dummy |
+----+------+------+------+-------+
| 11 | 1 | 1 | 1 | a |
+----+------+------+------+-------+
1 row in set (0.00 sec)
MariaDB [test]> select * from index_usage_copy;
+----+------+------+------+-------+
| id | a | b | c | dummy |
+----+------+------+------+-------+
| 99 | 1 | 1 | 1 | a |
+----+------+------+------+-------+
1 row in set (0.00 sec)
柜台
MariaDB [test]> SHOW status LIKE 'Handler_read_first';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| Handler_read_first | 59 |
+--------------------+-------+
1 row in set (0.00 sec)
第一个查询(没有 WHERE 1)增加 2
MariaDB [test]> SELECT * from index_usage WHERE EXISTS ( SELECT 1 FROM index_usage_copy where id in (1,2,99)); SHOW status LIKE 'Handler_read_first';
+----+------+------+------+-------+
| id | a | b | c | dummy |
+----+------+------+------+-------+
| 11 | 1 | 1 | 1 | a |
+----+------+------+------+-------+
1 row in set (0.00 sec)
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| Handler_read_first | 61 |
+--------------------+-------+
1 row in set (0.00 sec)
MariaDB [test]> SELECT * from index_usage WHERE EXISTS ( SELECT 1 FROM index_usage_copy where id in (1,2,99)); SHOW status LIKE 'Handler_read_first';
+----+------+------+------+-------+
| id | a | b | c | dummy |
+----+------+------+------+-------+
| 11 | 1 | 1 | 1 | a |
+----+------+------+------+-------+
1 row in set (0.00 sec)
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| Handler_read_first | 63 |
+--------------------+-------+
1 row in set (0.00 sec)
MariaDB [test]> SELECT * from index_usage WHERE EXISTS ( SELECT 1 FROM index_usage_copy where id in (1,2,99)); SHOW status LIKE 'Handler_read_first';
+----+------+------+------+-------+
| id | a | b | c | dummy |
+----+------+------+------+-------+
| 11 | 1 | 1 | 1 | a |
+----+------+------+------+-------+
1 row in set (0.00 sec)
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| Handler_read_first | 65 |
+--------------------+-------+
1 row in set (0.00 sec)
现在使用 WHERE 1 - 仅增加 1
MariaDB [test]> SELECT * from index_usage WHERE 1 OR EXISTS ( SELECT 1 FROM index_usage_copy where id in (1,2,99)); SHOW status LIKE 'Handler_read_first';
+----+------+------+------+-------+
| id | a | b | c | dummy |
+----+------+------+------+-------+
| 11 | 1 | 1 | 1 | a |
+----+------+------+------+-------+
1 row in set (0.00 sec)
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| Handler_read_first | 66 |
+--------------------+-------+
1 row in set (0.00 sec)
MariaDB [test]> SELECT * from index_usage WHERE 1 OR EXISTS ( SELECT 1 FROM index_usage_copy where id in (1,2,99)); SHOW status LIKE 'Handler_read_first';
+----+------+------+------+-------+
| id | a | b | c | dummy |
+----+------+------+------+-------+
| 11 | 1 | 1 | 1 | a |
+----+------+------+------+-------+
1 row in set (0.00 sec)
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| Handler_read_first | 67 |
+--------------------+-------+
1 row in set (0.00 sec)
MariaDB [test]>
此外, EXPLAIN FORMAT=JSON
表示 5.6 和 5.7 的“optimized_away_subqueries”。 8.0 和 MariaDB 10.2 和 10.3 没有这么说,但似乎无论如何都摆脱了子查询。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.