Как избежать выполнения дорогостоящего подзапроса дважды в объединении - PullRequest
0 голосов
/ 11 июня 2018

Я хочу объединить два запроса.Оба запроса используют внутреннее объединение в наборе данных, которое очень интенсивно вычисляется, но запрос набора данных одинаков для обоих запросов.Например:

SELECT veggie_id
FROM potatoes
INNER JOIN ( [...] ) massive_market
    ON massive_market.potato_id=potatoes.potato_id
UNION
SELECT veggie_id
FROM carrots
INNER JOIN ( [...] ) massive_market
    ON massive_market.carrot_id=carrots.carrot_id

Где [...] соответствует подзапросу, который занимает секунду для вычисления, и возвращает строки, по крайней мере, carrot_id и potato_id.

Я хочу, чтобы в моем общем запросе дважды не использовался запрос для массового рынка [...] .

Каков наилучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 22 июня 2018

Цель состоит в том, чтобы извлечь все повторяющиеся строки запроса из списка строк запроса, требующих повторных строк запроса.Таким образом, я держал картофель и морковь в одном подзапросе объединения и впоследствии помещал mass_market и вне этого объединения.

Это кажется очевидным, но мой вопрос возник из гораздо более сложного запроса, и работа, необходимая для реализации этой стратегиибыл немного более вовлеченным в моем случае.Для моего простого примера в моем вопросе выше, это разрешится примерно так:

SELECT veggie_id 
FROM (
  SELECT veggie_id, potato_id, NULL AS carrot_id FROM potatoes
  UNION
  SELECT veggie_id, NULL AS potato_id, carrot_id FROM carrots
) unionized
INNER JOIN ( [...] ) massive_market
  ON massive_market.potato_id=unionized.potato_id 
    OR massive_market.carrot_id=unionized.carrot_id
0 голосов
/ 11 июня 2018

Если для выполнения этого подзапроса требуется больше секунды, я бы сказал, что это связано с проблемой индексации, а не с самим запросом (конечно, если этот запрос не виден, то это несколько предположительно, я бы рекомендовал опубликоватьзапрос тоже).По моему опыту, 9/10 проблем с медленными запросами сводятся к неправильной индексации базы данных.

Убедитесь, что veggie_id, potato_id и carrot_id проиндексированы

Кроме того, если вы используете какие-либо объединения вПодзапрос mass_market, убедитесь, что столбцы, над которыми вы выполняете объединения, тоже проиндексированы.

Редактировать

Если индексация выполнена правильно, единственное другое решение, которое я могу себе представитьв верхней части моей головы это:

CREATE TEMPORARY TABLE tmp_veggies (potato_id [datatype], carrot_id [datatype]);

INSERT IGNORE INTO tmp_veggies (potato_id, carrot_id) select potatoes.veggie_id, carrots.veggie_id from [...] massive_market 
    RIGHT OUTER JOIN potatoes on massive_market.potato_id = potatoes.potato_id 
    RIGHT OUTER JOIN carrots on massive_market.carrot_id = carrots.carrot_id;
SELECT carrot_id FROM tmp_veggies
UNION
SELECT potato_id FROM tmp_veggies;

Таким образом, вы отменили запрос, поэтому он только один раз запускает массивный подзапрос, и UNION происходит во временной таблице (которая будетбудет сброшено автоматически , но не до тех пор, пока соединение не будет закрыто , поэтому вы можете удалить таблицу вручную).
Вы можете добавить любые необходимые столбцы в оператор CREATE TEMPORARY TABLE и SELECT

...