正在尝试优化一个需要很长时间才能执行的查询

zdwk9cvp  于 2021-06-19  发布在  Mysql
关注(0)|答案(2)|浏览(335)

基于以下查询的数据量,我的返回时间很慢。

mysql> explain select  *
    from  worker_location
    where  gate_id not in (
        SELECT  gate_id from  worker_address
                          );
+----+--------------------+---------------------+-------+---------------------------+---------------------------+---------+------+---------+--------------------------+
| id | select_type        | table               | type  | possible_keys             | key                       | key_len | ref  | rows    | Extra                    |
+----+--------------------+---------------------+-------+---------------------------+---------------------------+---------+------+---------+--------------------------+
|  1 | PRIMARY            | worker_location     | ALL   | NULL                      | NULL                      | NULL    | NULL |  527347 | Using where              |
|  2 | DEPENDENT SUBQUERY | worker_address      | index | gate_id_idx               | gate_id_ix                | 48      | NULL | 3041342 | Using where; Using index |
+----+--------------------+---------------------+-------+---------------------------+---------------------------+---------+------+---------+--------------------------+
2 rows in set (0.00 sec)

我试着使用左连接,但得到相同的计划,没有好处的速度。

mysql> explain select  *
    from  worker_location wl
    left join  worker_address wa  ON wl.gate_id=wa.gate_id
    where  wa.gate_id is null;
+----+-------------+-------+------+---------------+------+---------+------+---------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows    | Extra                                              |
+----+-------------+-------+------+---------------+------+---------+------+---------+----------------------------------------------------+
|  1 | SIMPLE      | wl    | ALL  | NULL          | NULL | NULL    | NULL |  527347 | NULL                                               |
|  1 | SIMPLE      | wa    | ALL  | NULL          | NULL | NULL    | NULL | 3041342 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+---------------+------+---------+------+---------+----------------------------------------------------+
2 rows in set (0.00 sec)

有没有办法进一步优化这个查询?

ukqbszuj

ukqbszuj1#

一些分析:
您必须接触第一个表的大约527347行。
对于每一个表,它都检查另一个表。
为什么是 gate_id 这么大?48字节??
第一个查询(不在中)使用索引(“using index”),因此对于527347随机查找相当有效。
第二个查询(左连接)加载整个索引。这可能比访问表527347次更有效,具体取决于缓存的内容。
第三种方法:

select  *
    from  worker_location AS wl
    where  NOT EXISTS ( SELECT 1 FROM worker_address WHERE gate_id = wl.gate_id );

每个变种需要多长时间?
为进一步讨论,请提供 SHOW CREATE TABLE 对于两个表和 innodb_buffer_pool_size . 这可能导致其他优化技术。

8tntrjer

8tntrjer2#

请参见解释输出中的两个问题:
未使用索引-请参阅“可能的\u键”和“键”列
“块嵌套循环”优化触发,可能会击中一个袋子
你可以尝试使用索引提示
和/或尝试通过以下方式禁用bnl: SET SESSION optimizer_switch='block_nested_loop=off';

相关问题