如果我执行查询,例如
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条件中只有一个inners子查询被执行,但是这里发生了同样的事情,两者都被执行但只使用了一个值。因此结果是正确的,但运行无用的查询。我试过CASE WHEN和同样的问题。不确定是不是因为我使用的是MariaDB或者我在这里缺少的东西。
答案 0 :(得分:0)
抱歉,我希望我能正确理解你的问题。在使用 WHERE 1 的第一个查询中,MySQL NEVER执行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 - 仅增加一个
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]>
答案 1 :(得分:0)
此外,EXPLAIN FORMAT=JSON
对于5.6和5.7说“ optimized_away_subqueries”。 8.0和MariaDB 10.2和10.3并没有这么说,但似乎还是摆脱了子查询。