Запрос Oracle SQL – неожиданный план запроса
-
19-09-2019 - |
Вопрос
У меня есть очень простой запрос, который дает неожиданные результаты.Подсказки, где устранить неполадку, приветствуются.
Упрощенно, запрос такой:
SELECT Obs.obsDate,
Obs.obsValue,
ObsHead.name
FROM ml.Obs Obs
JOIN ml.ObsHead ObsHead ON ObsHead.hdId = Obs.hdId
WHERE obs.hdId IN (53, 54)
Это дает мне стоимость запроса: 963.Однако, если я изменю запрос на:
SELECT Obs.obsDate,
Obs.obsValue,
ObsHead.name
FROM ml.Obs Obs
JOIN ml.ObsHead ObsHead ON ObsHead.hdId = Obs.hdId
WHERE ObsHead.name IN ('BP SYSTOLIC', 'BP DIASTOLIC')
Хотя он (должен) возвращать те же данные, предполагаемая стоимость возрастает до 17688.В чем здесь может заключаться проблема?Спасибо.
Редактировать: В плане запроса указано, что индекс на ObsHead.Name
используется для сканирования диапазона, а доступ к таблице в ObsHead стоит всего 4.Есть еще один индекс Obs.hdId
он используется для сканирования диапазона стоимостью 94:это соединение вложенных циклов между таблицами, размер которого увеличивается до 17 КБ.
Решение
Как уже было сказано, стоимость плана не предназначена для сравнения двух разных запросов, а только для сравнения разных путей по одному и тому же запросу.
Это всего лишь предположение, но в данном случае поле кардинальности плана может оказаться для вас более полезным.Если индекс OBSHEAD не уникален и статистика была собрана с использованием оценки, оптимизатор может не знать точно, сколько строк ожидать при запросе к этой таблице.Кардинальность подскажет вам, правда это или нет (в идеале вы увидите мощность 2 для OBSHEAD).
Еще совет — проверить статистику по OBS.Кажется вероятным, что эта таблица часто растет, и в этом случае 28 января не является достаточно свежим для сбора статистики.Предполагая, что для этой таблицы включен мониторинг, приведенные ниже запросы могут сообщить вам, устарела ли статистика и ее необходимо обновить.
select owner, table_name, last_analyzed, stale_stats
from all_tab_statistics
where owner = 'ML' and table_name = 'OBS';
select owner, index_name, last_analyzed, stale_stats
from all_ind_statistics
where owner = 'ML' and table_name = 'OBS';
Другие советы
Наверное, есть индекс hdId
(что есть, если это первичный ключ, что, как я подозреваю, так и есть), а не на name
это означает, что второй запрос должен будет выполнить полное сканирование таблицы.
Стоимость полезна только для сравнения различных планов по одному запросу;они не так полезны для сравнения разных запросов.
Вам необходимо посмотреть планы и сравнить их с точки зрения выполняемых ими действий.
Я подозреваю, что фактическая производительность этих запросов будет одинаковой, однако было бы интересно узнать, использует ли первый запрос хеш-соединение, что может помочь, если процент записей в obs
которые совпадают, имеют важное значение.
Я считаю, что затраты, предоставляемые оптимизатором, интересны, но не особенно полезны.Лучший способ, который я нашел для сравнения запросов, — это запустить их и посмотреть, как они работают относительно друг друга.
Делитесь и наслаждайтесь.