У меня сейчас очень медленный запрос.У этого запроса есть комбинированный запрос нашей позиции на акции (я называю это POSITION_QUERY
, есть одна строка для одного биржевого кода, торгующего на одной бирже в одну данную дату), затем присоединяется (я называю это FIRST JOIN
) к цене акции.В таблице, чтобы получить цену, условие соединения будет в трех столбцах: код акции, биржа и дата сделки.Тогда мне нужно SECOND JOIN
, потому что каждая акция принадлежит составному индексу (в POSITION_QUERY
каждая строка имеет столбцы, указывающие код индекса и биржу, на которой торгуется индекс).
Итак, мой запрос выглядит примерно так:
SELECT * FROM
POSITION_QUERY t1
JOIN DAILY_PRICE t2
on t1.STOCK_CODE = t2.STOCK_CODE
and t1.STOCK_EXCHANGE = t2.EXCHANGE
and t2.TRADE_DATE = 20181121
JOIN DAILY_PRICE t3
on t1.INDEX_CODE = t3.STOCK_CODE
and t1.INDEX_EXCHANGE = t3.EXCHANGE
and t3.TRADE_DATE = 20181121
И теперь запрос действительно очень медленный: около 3 минут, чтобы вернуть 50 строк результата.Как я уже говорил, POSITION_QUERY
на самом деле является запросом, а не существующей таблицей.Но если я запускаю SELECT * FROM POSITION_QUERY
, это все равно быстро (я получаю позицию только на 20181121 внутри POSITION_QUERY
, поэтому объем этого запроса уже равен 50, как я упоминал ранее).DAILY_PRICE
является view
, но почти сопоставлен с одной существующей таблицей, и у меня есть индексы для соединенных столбцов этой таблицы.
Странная вещь для меня, если я только выполняю POSITION_QUERY
, ИЛИ POSITION_QUERY
с FIRST JOIN
(то есть объединить DAILY_PRICE
с первым набором условий), ИЛИ POSITION_QUERY
с SECOND JOIN
(объединить DAILY_PRICE
со вторым набором условий), ВСЕ ТРИ запроса выполняются очень быстро (менее одной секунды).
Я проверил фактические планы выполнения, план с двумя объединениями и планы с одним объединением довольно похожи, но в плане с двумя объединениями есть table spool (lazy spool)
, стоимость которого составляет 49%.Выходной список оператора спулинга таблицы - POSOTION_QUERY
, поэтому я предполагаю, что он хранит результат 'POSITION_QUERY' (но почему это не последовательное соединение?).Я плохо интерпретирую планы выполнения, поэтому я не знаю, в этом ли проблема и как я могу ее исправить.
Обновление: я вставил свой план выполнения со структурой реальной таблицы данных и запросом.Ссылка: План выполнения