#oracle #performance #database-performance
#Oracle #Производительность #база данных-производительность
Вопрос:
я пытаюсь улучшить запрос. У меня открыт набор данных для запроса. Каждый билет имеет разные строки, каждая строка представляет собой обновление билета. Существует поле (dt_update), которое отличается в каждой строке.
У меня есть эти индексы в st_remedy_full_light.
IDX_ASSIGNMENT (ПРИСВОЕНИЕ)
IDX_REMEDY_INC_ID (REMEDY_INC_ID)
IDX_REMDULL_LIGHT_DTUPD (DT_UPDATE)
Теперь запрос выполняется за 8 секунд. Для меня высока.
WITH last_ticket AS
( SELECT *
FROM st_remedy_full_light a
WHERE a.dt_update IN
( SELECT MAX(dt_update)
FROM st_remedy_full_light
WHERE remedy_inc_id = a.remedy_inc_id
)
)
SELECT remedy_inc_id, ASSIGNMENT FROM last_ticket
Это план
Как я мог бы улучшить этот запрос?
P.S. Это всего лишь часть большого запроса
Дополнительная информация: — Таблица st_remedy_full_light содержит 529,507 строк
Комментарии:
1. Может ли быть несколько ‘st_remedy_full_light’ с одинаковым ‘dt_update’ для ‘remedy_inc_id’?
2. индекс (remedy_inc_id, dt_update) — или, возможно, даже (remedy_inc_id, dt_update, назначение) — должен помочь вам, если вы не хотите / не можете изменить подзапрос на то, что предлагает Тони Эндрюс. Т. Е. один индекс, содержащий несколько столбцов, а не индекс для каждого столбца — Oracle сможет использовать только один из этих индексов с одним столбцом для запроса, он не может использовать все три, даже если вы используете все три столбца в своем запросе . Такой индекс, вероятно, также помог бы предлагаемому запросу Тони Эндрю.
3. @EvgeniyK. не только у remedy_inc_id есть больше dt_update, но не у другого.
4. @Boneist Я не думал использовать несколько индексов. Поработайте над этим немного лучше с помощью (remedy_inc_id, dt_update, назначение). Но странно, что он использует индекс только для получения полей в select, а не для условия where в подзапросе
Ответ №1:
Вы могли бы попробовать:
WITH last_ticket AS
( SELECT remedy_inc_id, ASSIGNMENT,
rank() over (partition by remedy_inc_id order by dt_update desc) rn
FROM st_remedy_full_light a
)
SELECT remedy_inc_id, ASSIGNMENT FROM last_ticket
where rn = 1;
Комментарии:
1. Привет, Тони, спасибо за твой ответ… К сожалению, я использовал это решение, но, как ни странно, медленнее, чем мое решение.
2. Не могли бы вы поделиться более подробной информацией о том, почему этот запрос будет выполняться быстрее по сравнению с исходным.
3. @NzGuy Я бы ожидал , что он, вероятно , будет работать быстрее, потому что ему не нужно хэшировать соединение
last_ticket
с самим собой.4. @vecio88 Как выглядит план при использовании этого запроса?
5. Поскольку в запросе нет предложения where и нет объединений, использование индекса не ожидается. Требуется полное сканирование. Если вы добавили индекс на
(remedy_inc_id, ASSIGNMENT, dt_update)
, то Oracle может полностью сканировать его вместо таблицы, что было бы быстрее, если индекс намного меньше таблицы.
Ответ №2:
Лучшим альтернативным запросом, который также намного проще выполнить, является следующий:
select remedy_inc_id
, max(assignment) keep (dense_rank last order by dt_update)
from st_remedy_full_light
group by remedy_inc_id
При этом будет использоваться только одно полное сканирование таблицы и группировка (хэш / сортировка) по, без самосоединений.
Не беспокойтесь об индексированном доступе, поскольку вы, вероятно, обнаружите, что полное сканирование таблицы здесь наиболее уместно. Если таблица не является действительно широкой и составной индекс по всем используемым столбцам (remedy_inc_id, dt_update, назначение) будет значительно быстрее для чтения, чем таблица.