INSERT SELECT с помощью оператора UNION в условии WHERE - PullRequest
4 голосов
/ 12 марта 2020

У меня есть запрос, который выглядит примерно так:

INSERT IGNORE INTO `destination_table` (`id`, `field1`, `field2`, `field3`)
SELECT `id`, `field1`, `field2`, `field3`
FROM `source_table`
WHERE `source_table`.`id` IN (
    SELECT DISTINCT `id` FROM `some_table`
    UNION DISTICT SELECT DISTINCT `id` FROM `some_other_table`
);

Это не работает - запрос зависает бесконечно. Размер таблиц определенно не является проблемой, все таблицы имеют довольно небольшое количество записей (<100 000 записей). Запрос выполняется нормально и довольно быстро, если я запускаю его без <code>UNION:

INSERT IGNORE INTO `destination_table` (`id`, `field1`, `field2`, `field3`)
SELECT `id`, `field1`, `field2`, `field3`
FROM `source_table`
WHERE `source_table`.`id` IN (
    SELECT DISTINCT `id` FROM `some_table` -- I tried with `some_other_table` too, same result
);

или

INSERT IGNORE INTO `destination_table` (`id`, `field1`, `field2`, `field3`)
SELECT `id`, `field1`, `field2`, `field3`
FROM `source_table`

, которые работают и работают хорошо и быстро (менее чем за секунду). Итак, я думаю, что UNION DISTICT SELECT ... является виновником здесь, но я не знаю почему.

Что не так с этим запросом и почему он зависает?

Использование mysql 5.7 - это это имеет значение

Ответы [ 2 ]

2 голосов
/ 12 марта 2020

Ваш первый запрос, похоже, содержит несколько опечаток, но я бы посоветовал использовать существующую логи c здесь:

INSERT IGNORE INTO destination_table (id, field1, field2, field3)
SELECT id, field1, field2, field3
FROM source_table t1
WHERE
    EXISTS (SELECT 1 FROM some_table s1 WHERE s1.id = t1.id) OR
    EXISTS (SELECT 1 FROM some_other_table s2 WHERE s2.id = t1.id);

Возможное преимущество использования таким способом заключается в том, что MySQL может остановить поиск, как только он обнаружит первое совпадение id в любом из подзапросов в двух таблицах. Вы можете обнаружить, что добавление индекса для столбцов id в двух других может помочь (при условии, что id еще не проиндексирован):

CREATE INDEX some_idx_1 ON some_table (id);
CREATE INDEX some_idx_2 ON some_other_table (id);

Это должно ускорить поиск id в двух зависимых таблицах.

1 голос
/ 12 марта 2020

Вы можете обойти эту проблему, перефразировав запрос:

INSERT IGNORE INTO `destination_table` (`id`, `field1`, `field2`, `field3`)
SELECT `id`, `field1`, `field2`, `field3`
FROM `source_table`
WHERE `source_table`.`id` IN (
    SELECT DISTINCT `id` FROM `some_table`
)
OR `source_table`.`id` IN (
     SELECT DISTINCT `id` FROM `some_other_table`
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...