繁体   English   中英

Mysql在where子句中优化子查询

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM