Попытка оптимизировать запрос, выполнение которого занимает много времени - PullRequest
0 голосов
/ 28 сентября 2018

У меня медленное время возврата, основанное на количестве данных для следующего запроса.

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)

Есть ли способ оптимизировать этот запрос?

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Некоторый анализ:

  • Вам обязательно нужно дотронуться до 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 TABLE для обеих таблиц и значение innodb_buffer_pool_size.Это может привести к другим методам оптимизации.

0 голосов
/ 28 сентября 2018

см. В выходных данных объяснения две проблемы:

нет используемых индексов - см. Столбцы 'возможные_ключи' и 'ключевые'

Сработала оптимизация 'Блочный вложенный цикл', которая могла бы достичь bag

Вы можете попробовать играть с индексом подсказки

и / или попытаться отключить bnl с помощью: SET SESSION optimizer_switch='block_nested_loop=off';

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...