MySQL задыхается от IS NULL 11 000 записей

Я нашел аналогичный вопрос, который был решен с помощью индексов, но я не обнаружил изменений в скорости запроса, около 80 секунд, чтобы вернуть раздел игр. Это извлекает мета-значения из базы данных WordPress во временную таблицу, чтобы сравнить, соответствует ли обновленная временная метка славы или нет в опубликованном посте с помощью мета-значений поста. Я обнаружил, что g.game_updated != m.meta_value не отображается, когда m.meta_value равно NULL, без добавления запроса OR IS NULL менее 0,5 секунды, добавление делает это 80 секунд плюс с 10 800 записями. Добавление основного и обычного индекса к двум значениям не влияет

CREATE TEMPORARY TABLE tmp_meta
        SELECT distinct m.meta_value as game_id,m2.meta_value FROM wp_postmeta m
        INNER JOIN wp_postmeta m2
            ON m.post_id = m2.post_id
            AND m2.meta_key = 'game_updated'
            AND m.meta_key = 'game_id';

ALTER TABLE tmp_meta ADD PRIMARY KEY (game_id(100));
ALTER TABLE tmp_meta ADD KEY (meta_value(100));

CREATE TEMPORARY TABLE tmp_needsUpdate         
SELECT g.*,m.meta_value FROM wp_radium_games g 
    LEFT JOIN tmp_meta m 
    on m.game_id = g.game_id
    WHERE ( g.game_updated !=  m.meta_value OR m.meta_value IS NULL);
    

Удален последний запрос, так как он не имеет отношения к обсуждению того, почему добавление m.meta_value IS NULL добавляет к запросу 80 секунд.

+---------+--------------+------------+
| post_id |   meta_key   | meta_value |
+---------+--------------+------------+
|       1 | game_id      |        100 |
|       1 | game_updated |       9999 |
|       2 | game_id      |        101 |
|       2 | game_updated |       9997 |
|       3 | game_id      |        102 |
|       3 | game_updated |       9992 |
+---------+--------------+------------+

+---------+--------------+-----------+
| game_id | game_updated | game_name |
+---------+--------------+-----------+
|     100 |         9999 | game1     |
|     101 |         9999 | game2     |
|     102 |         9992 | game3     |
|     104 |         9992 | game4     |
|     105 |         3333 | game5     |
|     106 |         3333 | game6     |
+---------+--------------+-----------+

Это должно возвращать игры 101, 104, 105 и 106, поскольку 100 соответствует обновлению 9999, а 102 соответствует 9992. Игра 101 не соответствует game_updates, а 104–106 будут иметь нулевые значения.


person Radium Chris    schedule 29.11.2020    source источник
comment
LEFT JOIN... IS NOT NULL? Разве это не то же самое, что JOIN...   -  person Strawberry    schedule 29.11.2020
comment
Если вы имеете в виду tmp_needsUpdated, это необходимо, поскольку у нас должно быть больше игр, чем мета-значений, если нам нужно создать новый пост.   -  person Radium Chris    schedule 29.11.2020
comment
Помогите мне понять, почему g.game_updated != m.meta_value необходимо присоединение? почему !=? Примеры данных помогут   -  person xQbert    schedule 01.12.2020
comment
Я пока не понял, как добавить сюда данные, но причина в том, что у меня есть таблица игр, и в ней есть отметка времени обновления, когда игры добавляются или редактируются. Это переносится на сайт WordPress, и функция cron создает таблицу temp_meta, чтобы получить все игры, которые в настоящее время являются созданными сообщениями. Если временные метки не совпадают с game_updated на обоих, то сообщение об игре необходимо обновить, если мета-значения не существуют, значит, сообщение еще не создано, следовательно, NULL.   -  person Radium Chris    schedule 01.12.2020
comment
Можете ли вы поделиться планом выполнения долго выполняющегося запроса?   -  person Nico Haase    schedule 02.12.2020
comment
@Nico Haase На самом деле не нужен план выполнения, так как первый запрос создает временную таблицу, это быстро, не проблема, поэтому мы можем предположить, что она уже существует, а затем проблема в том, почему значение null ГДЕ убивает запрос.   -  person Radium Chris    schedule 02.12.2020
comment
@xQbert добавил образцы данных с ожидаемыми результатами.   -  person Radium Chris    schedule 02.12.2020


Ответы (1)


Я думаю, это ускорит запрос:

    LEFT JOIN tmp_meta m 
       ON m.game_id = g.game_id
       AND g.game_updated !=  m.meta_value
    WHERE m.meta_value IS NULL;

ON используется для обозначения того, как связаны таблицы; WHERE для фильтрации. Но шаблон LEFT JOIN...IS NULL проверяет, нашел ли LEFT JOIN совпадающую строку.

Другой подход — заменить LEFT JOIN на WHERE ... AND ( EXISTS SELECT 1 ... ).

Также полезными для производительности являются общие улучшения индекса для post_meta: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta

person Rick James    schedule 26.01.2021