|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
Всем привет! Делал тут одну задачку и что-то подвис. Соль в том, что оракл case обрабатывает как единый целый организм, а хотелось бы видеть классическую схему: первое условие проверили, потом пошли на второе и т.д. Ниже запрос как пример. Если убрать "when 1=2 ****", то время выполнения многократно увеличивается. Если у кого-то боевые комплексы или мощные, то поставьте level <100 допустим. Итак: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
План приложу, он адаптивный, но думаю тут роли не играет: Код: 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. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88.
Имхо всё дело в этой строке плана: 6 - filter(CASE WHEN 1=1 THEN 1 WHEN (1=2 AND INSTR("AGENT_NAME","OBJECT_NAME")>0) THEN 2 ELSE 0 END =1) т.е. оракл все делает именно за раз. Может кто-то сталкивался уже с таким поведением, а как избежать такого поведения через хинты или может переписать запрос( !!без конструкции with!! ). Через with понятно, что проблем нет, но в моем случае подобных условий ровно три и как-то ну сильно читаемость кода теряется. Я сам пробовал и через decode, coalesce, через case вложенный в case. Что-та не вышло. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 10:58 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
Был древний хинт ORDERED_PREDICATE Но с представлиниями он может не дать ожидаемого результата Еще есть всякие rownum>100000000, materialized и т.п. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 11:04 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
Вячеслав Любомудров, ORDERED_PREDICATE я первым попробовал, но...А что касается materialized и т.п. они тут профита точно не дадут т.к. тогда нужна обертка через with. Про rownum не понял если честно, но думаю это из другой оперы. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 11:15 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
Любой подзапрос можно оформить с materialized Ограничение по rownum запрещает слияние условий основного запроса с представлением, что, как обычно, и приводит к неоптимальным планам with -- оно только для красоты, select from (select) мало чем отличается ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 11:23 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
Вячеслав Любомудров, ну конечно имелось ввиду без использования with или подзапросов. Смысл materialized в материализации запроса, без конструкции with или подзапросов особого смысла в ней не вижу. Хотя написать вам никто не мешает. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 12:28 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
Pavel_PV Имхо всё дело в этой строке плана: 6 - filter(CASE WHEN 1=1 THEN 1 WHEN (1=2 AND INSTR("AGENT_NAME","OBJECT_NAME")>0) THEN 2 ELSE 0 END =1) т.е. оракл все делает именно за раз. при простом Код: plsql 1. 2. 3. 4.
оптимизатор видит, что выражение статичное, без входных/меняющихся параметров и всегда положительное, поэтому просто удаляет его из запроса А в случае Код: plsql 1. 2. 3. 4. 5.
оптимизатор видит, что для выражения требуются поля (agent_name, OBJECT_NAME) и строит другой план с передачей этих полей (см. секцию projection) Проверяется крайне легко: создай свою функцию Код: plsql 1. 2. 3. 4. 5. 6. 7.
и подсунь ее в запрос и увидишь, что она не вызывалась: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 12:50 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
Если нужно получить ответ уже после первого условия, то нет смысла указывать несколько условий в качестве одного. Всегда можно сделать кейс в несколько уровней, где каждое условие будет выдавать булину, по которой мы либо идём на выход, либо проверяем дальше. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 13:31 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
Офк основной ELSE нужно выносить в каждый такой кейс, пересекающиеся условия должны быть под одним уровнем и т.д. Например, условия: Код: plsql 1. 2. 3. 4. 5. 6. 7.
Должны выглядеть как: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9.
Но в целом, как я и написал выше, если нужно получать булину после проверки каждого условия, то так и пиши. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 13:44 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
Ребята, спасибо что по делу! xtender, я понял о чем ты. Блин, возможно пример аналогичный я не совсем удачный привёл. Т.е. суть в том, что да получается тут instr не вызывается, но бегло я не смог объяснить откуда получился такой лаг во времени. Если убрать instr, то у меня запрос обрабатывается 0.5сек, а с ним уже 14сек. Но в этом случае наверное дело именно в просто "транспортировке" 2х колонок и не важно, что дальше они не нужны. Dshedoo, хех. Ну да хитро, только тут немного так сказать меняется суть. В твоем случае нужно 1=2 заменить на 2=2, чтобы именно показать что со вторым условием время существенно изменяется: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
В общем я понял, что пример мой не айс. Надо более сложный, надо чтобы всегда была проекция в запросе. Постараюсь сделать на выходных, гляну проекции. Ну или может просто пойму, что был не прав. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 04:37 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
на оракле 11.2 какие-то другие результаты? Код: sql 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. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70.
... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 13:41 |
|
Определить порядок предикатов в oracle
|
|||
---|---|---|---|
#18+
andreymx на оракле 11.2 какие-то другие результаты? ... почему бы им и не быть другими, если, например, "в отсутствии instr" у него, например, join elimination возникает, а в присутствии нет. И вообще, в условиях, когда "case обрабатывает как единый целый организм", может быть вообще всё, что угодно. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 15:37 |
|
|
start [/forum/topic.php?fid=52&msg=39986987&tid=1880996]: |
0ms |
get settings: |
10ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
61ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
44ms |
get tp. blocked users: |
1ms |
others: | 321ms |
total: | 467ms |
0 / 0 |