powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Потрогать пустой result set
25 сообщений из 27, страница 1 из 2
Потрогать пустой result set
    #40000095
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нашел баг в оракле 11.2. Похоже что в оптимизаторе.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
SQL>  select * from (
  2         select fPrint('error ' || t.doc_id) as bug from DOCS t
  3          where t.doc_id = 50128384 and t.doc_type_id < 0
  4  ) p where p.bug is not null;
BUG
--------------------------------------------------------------------------------
error 50128384



Внутренний селект пустой, (doc_type_id всегда положителен).
Внешний селект умудряется потрогать строчку в пустой таблице,
как видно по распечатке.

Баг достаточно хрупкий, если попытаться узнать номер строчки или любые другие ее атрибуты, баг пропадает.
На маленьких таблицах тоже не случается, нужны тысячи строчек.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000103
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это не баг, для этого есть другой термин - "трансформация запроса".
Система считает себя вправе преобразовать твой запрос к виду

Код: plsql
1.
2.
3.
4.
5.
6.
 Select 
   fPrint('error ' || t.doc_id) as bug 
 From DOCS t
 Where 
         t.doc_id = 50128384 and t.doc_type_id < 0
  And fPrint('error ' || t.doc_id) is not null



(Возможно, именно об этом думал Elic, высказывая сомнение в полезности раннего знания о флаге deterministic.)

А вообще, скажи системе, что тебе этого не надо, превратив инлайн вью в non mergeable,
или явно запрети ей попытки трансформации соответствующим хинтом.

на будущее - порядок выполнения функции и количество ее вызовов в запросе официально не определяется,
никак, хотя известны случаи устойчивого поведения, на которые можно более-менее положиться.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000104
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кстати, тебе нравятся запросы сорта
Select *
From (
Select function(someparam) as p
From table
) t
Order by p

Так вот, строго говоря, никаких обещаний по количеству раз, которое будет вызвана function
Oracle принципально не дает, оставляя за собой право вычислять ее столько раз, сколько ему понадобится в процессе сортировки,
кроме некоторых, официально не оговорённых, но на практике известных случаев.

Работа с функцией в запросе, и особенно пользовательской, это всегда счастье и гордость от быстрого и умелого освоения инструмента.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000106
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
booby
это не баг, для этого есть другой термин - "трансформация запроса".
Система считает себя вправе преобразовать твой запрос ..

А вообще, скажи системе, что тебе этого не надо, превратив инлайн вью в non mergeable,
или явно запрети ей попытки трансформации соответствующим хинтом.


Это интересно, я наивно полагал что скобки определяют порядок операций, и после внутренней пустышки дело дальше не пойдет,
а оказывается это вовсе не так и скобки контролируют не это.

То, что в самом WHERE порядок вычисления (не порядок эвалюации) условий произвольный и непредсказуемый, я уже прочитал.

Я попробовал преобразованный пример из твоего ответа - функция вызывается, из условия WHERE, как и ожидалось (я там поменял текст). Т.е. оптимизатор посчитал нужным вызвать недерминистическую функцию до того, как сравнивать простые числа.

Код: plsql
1.
2.
3.
4.
5.
6.
Select 
   fPrint('error ' || t.doc_id) as bug 
 From DOCS t
 Where 
         t.doc_id = 50128384 and t.doc_type_id < 0
  And fPrint('from where ' || t.doc_id /* || t.doc_type_id */) is not null



Хотя, если попросить распечатать атрибут (закомментированый выше), то оптимизатор меняет свое мнение и больше функцию не вызывает. Или на маленьких таблицах. Или на больших новых таблицах. Возможно, оптимизатор убежден, что читать поле doc_type_id из уже известной строчки слишком дорого.

По поводу вызывания функций в селекте - так ведь виртуальные колонки так и работают.
Я выбрал функцию с заметным побочным эффектом потому что мне интересно как оптимизатор работает.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000110
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000111
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
booby

(Возможно, именно об этом думал Elic, высказывая сомнение в полезности раннего знания о флаге deterministic.)
.
наоборот, детерминистик в запросе уменьшает неконсистентность за счёт уменьшения количества вызовов
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000156
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL
Возможно, оптимизатор убежден

Ну так посмотри план выполнения. Предположу, что он другой для запроса с doc_type_id, т.к. при наличии индекса на doc_id в первом случае фильтр по функции не требует извлечения строки таблицы.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000157
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL
Или на маленьких таблицах. Или на больших новых таблицах.

Фазы Луны и положение Меркурия в Скорпионе забыли.

Начните уже читать документацию и литературу по теме.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000161
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby
это не баг , для этого есть другой термин - "трансформация запроса".
Система считает себя вправе преобразовать твой запрос к виду

Код: plsql
1.
2.
3.
4.
5.
6.
 Select 
   fPrint('error ' || t.doc_id) as bug 
 From DOCS t
 Where 
         t.doc_id = 50128384 and t.doc_type_id < 0
  And fPrint('error ' || t.doc_id) is not null



(Возможно, именно об этом думал Elic, высказывая сомнение в полезности раннего знания о флаге deterministic.)

А вообще, скажи системе, что тебе этого не надо, превратив инлайн вью в non mergeable,
или явно запрети ей попытки трансформации соответствующим хинтом.

на будущее - порядок выполнения функции и количество ее вызовов в запросе официально не определяется,
никак, хотя известны случаи устойчивого поведения, на которые можно более-менее положиться.


почему не баг?

ф-ция хоч 100 раз пусть вызывается
doc_type_id всегда положителен , строки не должны возвращатся при and t.doc_type_id < 0


.....
stax
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000184
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax,

Так они и не вернулись.
Всё в порядке.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000190
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby
Stax,

Так они и не вернулись.
Всё в порядке.


он что руками набрал?

BUG
--------------------------------------------------------------------------------
error 50128384

ps
запутался я
......
stax
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000191
Фотография кит северных морей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
del
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000200
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax,

Первый ответ в теме.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000202
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Без трейса 10053 или хотя бы планов, нет никакого смысла это обсуждать. Тем более непонятно на какой версии 11.2.?.?
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000219
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
env
Stax,

Первый ответ в теме.


я понимаю что ф-ция может вызываться (как и показано),
но селект полюбому не должен возвращать строку

BUG
--------------------------------------------------------------------------------
error 50128384

ps
no rows selected / "пусто", но не строку
.....
stax
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000228
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Стас, скорее всего тут no rows selected + аутпут функции фпринт.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000231
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
env,

Ага, скорее всего, тупо feedback выключен
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000236
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xtender
env,

Ага, скорее всего, тупо feedback выключен

имхо шапочку не введет
BUG
--------------------------------------------------------------------------------


......
stax
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000347
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Stax,

"error 50128384" это был результат output.

Строчек вернулось ноль, как и ожидалось.

Со счетчиком было бы понятнее.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
SQL> select /*+ RULE */ count(*) from (
  2           select fPrint('error ' || t.doc_id) as bug from DOCS t
  3            where t.doc_id = 50128384 and t.doc_type_id < 0
  4    ) p where p.bug is not null
  5  /
  COUNT(*)
----------
         0
error 50128384



План показывает такой (удалил пустые столбцы). Надеюсь когда-нибудь научиться читать такие вещи. Жаль, что функцию не упоминает.

Код: plaintext
1.
2.
3.
4.
5.
Description                           Object Name   ID  Instance  Object Type    Operation          Optimizer     Options         Parent ID  Position  Search columns
SELECT STATEMENT, GOAL = HINT: RULE                  0                           SELECT STATEMENT   HINT: RULE
 SORT AGGREGATE                                      1                           SORT                             AGGREGATE          0         1
  TABLE ACCESS BY INDEX ROWID           DOCS         2      2     TABLE          TABLE ACCESS       ANALYZED      BY INDEX ROWID     1         1
   INDEX UNIQUE SCAN                  PK__DOCS       3            INDEX (UNIQUE) INDEX              ANALYZED      UNIQUE SCAN        2         1          1
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000355
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
НеофитSQL,

1. еще раз смотри сообщение выше: 22199705
2. RULE - нахрена?
3. планы надо показывать нормально через dbms_xplan со всеми нужными секциями. Если не знаешь какие, показывай с параметром 'advanced'.
4. в выводе dbms_xplan есть секция projections, по ней видно на какой строке плана он ее вызывает.
5. не надо переформатировать вывод из sqlplus. В данном случае ты буквально всех обманул в стартовом посте ложным выводом.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000381
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
xtender
НеофитSQL,

1. еще раз смотри сообщение выше: 22199705
2. RULE - нахрена?
3. планы надо показывать нормально через dbms_xplan со всеми нужными секциями. Если не знаешь какие, показывай с параметром 'advanced'.
4. в выводе dbms_xplan есть секция projections, по ней видно на какой строке плана он ее вызывает.
5. не надо переформатировать вывод из sqlplus. В данном случае ты буквально всех обманул в стартовом посте ложным выводом.


1. Да, я прочитал. Как уже видно из текста, я не знал об оптимизации merge раскрывающий подчиненный селект.
2. Это один из хинтов, с которыми я экспериментировал.
3. Гуглю dbms_xplan. Благодарю за наводку.
..
5. Взял с экрана как есть, ничего не редактировал. Было бы удобнее если бы мой PL/SQL Developer показывал <empty result set> или что-то подобное, чтоб народ на форуме не обманывать. Наверное в следующий раз от руки напишу, будет вот так:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 Select /*+ RULE */
SQL> set serveroutput on
SQL> 
SQL>  Select /*+ RULE */
  2     besapi.fPrint('error ' || t.doc_id) as bug
  3   From DOCS t
  4   Where
  5           t.doc_id = 50128384 and t.doc_type_id < 0
  6    And besapi.fPrint('or ' || t.doc_id) is not null
  7  /
BUG
--------------------------------------------------------------------------------
 Эта строка ручной работы. Тут ничего не было, т.к. ноль строк. Следующая строка это печать из функции. 
or 50128384

SQL> dbms_xplan
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000415
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Поигрался еще. Добавил "no merge" во внутренний селект, а потом уже везде где можно.

План поменялся (т.е. "no merge" был замечен), но поведение осталось прежним - продолжает печатать на экран.

Код: plsql
1.
2.
3.
4.
select /*+ no_merge */ count(*) from (
         select /*+ no_merge */ fPrint('error ' || t.doc_id) as bug from DOCS t
          where t.doc_id = 50128384 and t.doc_type_id < 0
  ) p where p.bug is not null



Переделал как инлайн-вью. Ничего не поменялось, печатает (ожидаемо)

Код: plsql
1.
2.
3.
4.
with v_no_rows as (select /*+ no_merge */ fPrint('error ' || t.doc_id) as bug from DOCS t
                   where t.doc_id = 50128384 and t.doc_type_id < 0)

select /*+ no_merge */ count(*) from v_no_rows p where p.bug is not null



Остается вопрос, как оптимизатор заключил что вызов функции дешевле, чем фетч одного числа по известному ROWID.
Функция явно тяжеловесная даже на вид, требует перехода в другой контекст, и т.д.

Этот опыт хорошо доносит идею, что "view" это далеко не резалт сет, а только рецепт как его получить.
И даже если вью само по себе пустое (всегда возвращает ноль строчек), это еще не гарантия что к полям
несуществующих строчек этого вью кто-то снаружи не дотронется.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000421
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
НеофитSQL,

Ещё раз 22200153
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000427
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Может, вернется Booby и пояснит, почему запрет 22199697 на merge optimization не повлиял на поведение.
...
Рейтинг: 0 / 0
Потрогать пустой result set
    #40000428
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
НеофитSQL,

ты когда прочитаешь вторую ссылку в том сообщении? Полностью, до конца, вдумчиво...
...
Рейтинг: 0 / 0
25 сообщений из 27, страница 1 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Потрогать пустой result set
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]