|
|
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
Была задача сгенерировать случайные пары чисел (s, e) такие, что s <= e . Для этого решил выбирать пары значений dbms_random.value в подзапросе, и при необходимости переставлять значения в паре, чтобы соблюсти условие s <= e . Перестановку можно написать с помощью least и greatest , но можно и вручную с помощью case . Однако выясняется, что вариант с case совсем не прост, я не могу понять логику его работы. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. Этот запрос порождает, например, такие результаты: Код: plaintext 1. 2. Обратите внимание, перестановка не требовалась, она не была заложена в логике case -операторов, но она произошла. Почему? Почему least и greatest сработали правильно, а case - нет? Последние делают перестановку независимо от исходных данных. Причём, если заменить именованный запрос rnd на тот, что закомментирован в строке №3, то всё заработает: Код: plaintext 1. 2. Если не заменять выборку, а добавить к случайным числам фиксированные, раскомментировав строчки 1 и 2, то всё будет работать правильно: Код: plaintext 1. 2. 3. 4. Также всё будет работать, если в первый и второй case вставить дополнительное условие, например Код: plsql 1. 2. 3. или если в case произвести с возвращаемыми s или e математические действия, не меняющие их значений: Код: plsql 1. 2. 3. 4. Я подменял обращения к dbms_random на свою функцию, генерирующую последовательные номера, и проверял, что она вызывается лишь дважды. План выглядит так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Подскажите, пожалуйста, в чём подвох? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.07.2016, 20:55:20 |
|
||
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
NLK, План с проекцией. И версию. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.07.2016, 21:09:03 |
|
||
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
-2-, Код: 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. Версия Код: plaintext 1. 2. 3. 4. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.07.2016, 21:19:48 |
|
||
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
NLK, Лишнее из тест кейса лучше выкидывать и выполнять dbms_random.seed для воспроизводимости. Но баг конечно эпичен. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 10053 final query Код: plsql 1. 2. 3. 4. 5. 6. 7. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.07.2016, 21:35:46 |
|
||
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
Это клиника, конечно... (и дело не в dual) workaround Код: 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.07.2016, 21:51:19 |
|
||
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
dbms_photoshop... [/src]10053 final query Код: plsql 1. 2. 3. 4. 5. 6. 7. не знаю, чем это является, но выглядит как "оптимизация". Типа, case оптимизирован целиком путем подсмотра исходных значений при построении плана запроса. А decode при этом не ломают - не оптимизируют. (спасибо) Код: plsql 1. вполне работает. На то, что оптимизация, намекает таблетка вида добавленной в case ветки Код: plsql 1. Здесь уже становится совершенно ясно, что case исключать целиком больше нельзя, т.к. рано или поздно 1 станет равным 2, и тогда... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.07.2016, 22:23:15 |
|
||
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
dbms_photoshop, booby, Да, видимо, здесь странно поработал оптимизатор. Нашёл ещё на Ask Tom обсуждение поведения dbms_random в запросах. Пара цитат оттуда: I've written thousands of times that you cannot rely on how many times or when or if SQL will call your function. When calling functions from SQL, you had better not rely on how often the functions get called, in what order, or whatever. In short, assume nothing. And people do need to watch out for constructs like: Код: plsql 1. it won't return 10% of the table (sample does that). It might return no rows or every row И в моём примере использование least вместо case помогает, если использовать хинт materialize , а вот с inline — нет. Например: Код: plsql 1. 2. 3. 4. 5. 6. Здесь pk_sq.next — генератор последовательных чисел, начиная с 1. В общем, использование недетерминированных функций с побочными эффектами в запросах в общем случае небезопасно. Сложно гарантировать, порядок и количество вызовов. Каждый раз подбирать workaround и проверять работоспособность в конкретных условиях. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.07.2016, 18:13:20 |
|
||
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
Как тут уже выяснили уже предыдушие ораторы :) конечно, материализация результата рандома необходима, до начала прочей арифметики. хинтом ли материализовать - это уже детали. главное, чтобы в последующие арифметики рандом не про-инлайнился ну и, кстати, баян же ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.07.2016, 19:12:41 |
|
||
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
orawish, Если читать не по диагонали, то можно заметить, что материализация здесь не помогла. В изначальном примере автора материализация имеет место, просто case полностью пропадает в final query. Ну а то, что автор написал в последнем сообщении - баян, да. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.07.2016, 19:22:00 |
|
||
|
Странности CASE при использовании подзапроса с функциями
|
|||
|---|---|---|---|
|
#18+
dbms_photoshoporawish, Если читать не по диагонали, то можно заметить, что материализация здесь не помогла. В изначальном примере автора материализация имеет место, просто case полностью пропадает в final query. Ну а то, что автор написал в последнем сообщении - баян, да. ну, ок Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. из результатов коего вывод - привет хинту (12.1) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.07.2016, 22:50:10 |
|
||
|
|

start [/forum/topic.php?fid=52&fpage=209&tid=1887774]: |
0ms |
get settings: |
9ms |
get forum list: |
21ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
522ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
51ms |
get tp. blocked users: |
2ms |
| others: | 198ms |
| total: | 827ms |

| 0 / 0 |
