尝试优化执行时间较长的查询

Posted

技术标签:

【中文标题】尝试优化执行时间较长的查询【英文标题】:Attempting to optimize a query that is taking a long time to execute 【发布时间】:2018-09-27 21:19:22 【问题描述】:

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

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)

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

【问题讨论】:

确保只选择您需要的列。不要使用 * 并获取您不需要的不必要的列。 所有列都需要。 你有worker_location.gate_id 列的索引吗? 是的,所有列都已编入索引。 无能为力。可以尝试增加会话join_buffer_size,BNL和BKA 【参考方案1】:

在您的解释输出中看到两个问题:

没有使用索引 - 请参阅“possible_keys”和“key”列

触发了“阻止嵌套循环”优化,可能会遇到bag

你可以尝试使用 index hints 玩游戏

和/或尝试通过以下方式禁用 bnl: SET SESSION optimizer_switch='block_nested_loop=off';

【讨论】:

【参考方案2】:

一些分析:

您必须要触摸第一个表格的大约 527347 行。 对于其中的每一个,它都会检查另一个表。 为什么gate_id 这么大? 48 字节?? 第一个查询(NOT IN)使用索引(“使用索引”),因此对于 527347 次随机查找相当有效。 第二个查询 (LEFT JOIN) 加载整个索引。这可能比访问表格 527347 次更有效,具体取决于缓存的内容。

第三种方法:

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

每个变体需要多长时间?

如需进一步讨论,请提供两个表的SHOW CREATE TABLEinnodb_buffer_pool_size 的值。这可能会导致其他优化技术。

【讨论】:

以上是关于尝试优化执行时间较长的查询的主要内容,如果未能解决你的问题,请参考以下文章

Dynamics 365同一个消息的多个插件步骤执行时间较长的测试

项目之接口响应慢排查

php pdo预处理语句与存储过程

线程阻塞导致的性能问题分析

优化 SQL 查询以避免重复

MySQL性能优化