|
Не используется индекс на следующий день
|
|||
---|---|---|---|
#18+
Здравствуйте. При выполнении плана запроса на следующий день, отображается другой план запроса и индексы перестают использоваться (при этом Cost возрастает в 2 раза). Есть 2 таблицы (БД Oracle 12.2.0.1.0): DEPARTMENT_DOC_MASTER Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.
DEPARTMENT_DOC_VERSION Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28.
Выполняется соединение этих двух таблиц по внешнему ключу DEPARTMENT_DOC_VERSION.DEPARTMENT_DOC_MASTER_ID: Этот запрос ORM Hybernate (Java) отправляет на выполнение Oracle Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44.
Исходный запрос выглядит немного компактнее (но не в этом суть) Код: java 1. 2. 3. 4. 5.
После создания индекса план запроса выглядит следующим образом (Cost = 445, индексы используются): Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.
А на следующий день план запроса меняется на этот (Cost = 997, индексы не используются): Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
В соседнем форуме ( 22339748 ) рекомендовали собрать статистику по индексам сразу после их создания. Выполнял: Код: plsql 1. 2. 3. 4. 5.
Но на следующее утро план менялся и Cost снова вырос (индексы не использовались). После сбора статистики по таблице (ниже под спойлером) план запроса сразу становился равен 997. Код: plsql 1. 2. 3. 4.
Подозреваю, что Oracle автоматически выполняетет сбор статистики по таблице ночью, а на утро получаю другой план запроса. Есть ли какие-нибудь способы, чтобы план запроса оставался равным 445 (как сразу после создания индексов) и индексы использовались постоянно? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.06.2021, 14:04 |
|
Не используется индекс на следующий день
|
|||
---|---|---|---|
#18+
Нашёл подобный вопрос Как отключить сбор статистики для конкретной таблицы? и статью How to lock/unlock statistics on a table? Возможно, это поможет? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.06.2021, 14:43 |
|
Не используется индекс на следующий день
|
|||
---|---|---|---|
#18+
Может тогда лучше закрепить план? dbms_spm ... |
|||
:
Нравится:
Не нравится:
|
|||
25.06.2021, 14:46 |
|
Не используется индекс на следующий день
|
|||
---|---|---|---|
#18+
chikaginsk, Для начала убери условие: Код: sql 1.
Оно избыточно так как покрывается условием: Код: sql 1.
Затем сравниваем вышестоящее условие с Код: sql 1. 2.
и понимаем что оно использует индекс наполовину. Поменяй индекс на (или создай новый если существующий, вернее его часть TRUNC("CLOSE_DATE") используется в других SQL) Код: sql 1. 2.
а условие на: Код: sql 1.
Далее, обрати внимание на "this is an adaptive plan". В 12C adaptive уж очень сырой - в 12.2 Oracle даже изменил optimizer_adaptive_statistics на FALSE (проверь свою базу), но все равно adaptive зачастую порождает кучу child cursor да еще и неоптимальных. Попробуй запретить adaptive хинтом Код: plsql 1.
SY. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.06.2021, 15:38 |
|
Не используется индекс на следующий день
|
|||
---|---|---|---|
#18+
SY chikaginsk, ...Поменяй индекс на (или создай новый если существующий, вернее его часть TRUNC("CLOSE_DATE") используется в других SQL) Код: sql 1. 2.
а условие на: Код: sql 1.
Благодарю за ответ. Условие Код: plsql 1.
изначально так себе и представлял, но была проблема с передачей даты (TIMESTAMP) в функцию COALESCE() - та же NVL() в Oracle. Никак не получалось передать параметром дату в функцию. Рассматривал вариант с CURRENT_TIMESTAMP, но очень удачно удалось "подружить" TRUNC и CURRENT_DATE, чтобы оставить только "год-месяц-день". SY Далее, обрати внимание на "this is an adaptive plan". В 12C adaptive уж очень сырой - в 12.2 Oracle даже изменил optimizer_adaptive_statistics на FALSE (проверь свою базу), но все равно adaptive зачастую порождает кучу child cursor да еще и неоптимальных. Попробуй запретить adaptive хинтом Код: plsql 1.
SY. Использовать хинты не получится, т.к. исходный запрос вызывается в ORM Hybernate (нижний запрос под вторым спойлером в головном сообщении), а он в свою очередь уже строит запрос для Oracle (верхний запрос с кучей полей в select под вторым спойлером в головном сообщении). План запроса после создания индекса меня устраивает. Пока проблема в том, что на следующий день индекс перестаёт использоваться и план запроса меняется в худшую сторону. Вот с этим бы разобраться. А какая альтернатива (более точное опрелеление производительности запроса) есть планам запроса в 12c? Слышал про трассировки (могу ошибаться). Сам я в Oracle, можно сказать "чайник", знаю только по верхам (по чтению статей, документации и по советам опытных людей, в том числе на этом замечательном форуме). Сталкиваюсь с подобными задачами эпизодически. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.06.2021, 16:41 |
|
Не используется индекс на следующий день
|
|||
---|---|---|---|
#18+
chikaginsk, Ну тогда создай SQL profile с "хорошим" планом или "Может тогда лучше закрепить план? dbms_spm" как советовал Вячеслав. Или попробуй отключить adaptive на уровне сессии/базы. SY. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.06.2021, 18:19 |
|
|
start [/forum/topic.php?fid=52&fpage=16&tid=1880085]: |
0ms |
get settings: |
10ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
44ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
45ms |
get tp. blocked users: |
1ms |
others: | 32ms |
total: | 168ms |
0 / 0 |