powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / функция и в select-листе и в where
8 сообщений из 8, страница 1 из 1
функция и в select-листе и в where
    #39595976
Teaser_for_newbie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток, уважаемый All!

Вот пример

Код: plsql
1.
2.
select colA, colB, func(colC) 
from some_table where func(colC) > 5 



Скажите, Oracle отложит вычисление функции до шага filter в плане запроса,
или же в момент размещения блока данных в кэше?
Ведь не будет же он ее вычислять дважды?

Заранее спасибо!
...
Рейтинг: 0 / 0
функция и в select-листе и в where
    #39595985
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Teaser_for_newbieВедь не будет же он ее вычислять дважды?Легко.
...
Рейтинг: 0 / 0
функция и в select-листе и в where
    #39596124
Gollum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я Вам больше скажу, он с нее НАЧНЕТ. В шаге filter
...
Рейтинг: 0 / 0
функция и в select-листе и в where
    #39596197
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Teaser_for_newbieСкажите, Oracle отложит вычисление функции до шага filter в плане запроса,


Как ты думаешь, что Oracle должен сделать с каждой строкой таблицы some_table чтобы понять подходит ли строка под запрос или нет? Правильно, Oracle выполнит ф-цию func(colC) для каждой строки. Это в общeм случае. Но если func определена как deterministic и есть FBI на func(colC), то func(colC) при запросе вообще не будет вычисляться. А если func определена как deterministic и result_cache то число выполнений func(colC) будет меньше или равно числу строк таблицы some_table.

SY.
...
Рейтинг: 0 / 0
функция и в select-листе и в where
    #39596345
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я так понимаю, что у Oracle проблема. что у него только один шаг filter. Поэтому если в filter на таблице попадают и "нормальные операции" ))) и функции, программист надеется, что "Oracle умный" и вычислив обычные выражения, функцию и трогать не будет. А для оптимизатора, это просто filter... и он его как попросили, так и обрабатывает... а строк в таблице может быть много.

Как вариант, можно сделать подселект который выбирает данные, добавить туда rownum (что бы сматериализовать), а во внешнем селекте дополнительно отфильтровать по функции. Иногда помогает.

select * from (select .., rownum r from ... where .... ) tt where ...=my_func()

Недавно коллеги тоже с функцией мучились (добавить rownum забыли)

IMHO & AFAIK
...
Рейтинг: 0 / 0
функция и в select-листе и в where
    #39596400
Teaser_for_newbie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SY
А если func определена как deterministic и result_cache то число выполнений func(colC) будет меньше или равно числу строк таблицы some_table.
SY.

Спасибо за совет! А может только result_cache хватит для того,
чтобы число выполнений функции не превышало числа строк таблицы? Без deterinistic?
...
Рейтинг: 0 / 0
функция и в select-листе и в where
    #39596455
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Teaser_for_newbieА может только result_cache хватит для того,


Ну тут ситуация двоякая. Да result_cache не требует deterministic но подразумевает(правда частично). В древних версиях необходимо было указывать RELIES_ON теперь ORACLE автоматом их определяет. Но это только SQL data sources, a вот PL/SQL:

Код: 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.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
SQL> SELECT  DBMS_RESULT_CACHE.status
  2    FROM  DUAL
  3  /

STATUS
--------------------------------------------------------------------------------
ENABLED

SQL> EXEC DBMS_RESULT_CACHE.MEMORY_REPORT(DETAILED => TRUE)

PL/SQL procedure successfully completed.

SQL> CREATE OR REPLACE
  2    PACKAGE PKG1
  3      IS
  4          FUNCTION F_RESULT_CACHE
  5            RETURN NUMBER
  6            RESULT_CACHE;
  7          FUNCTION F_NO_RESULT_CACHE
  8            RETURN NUMBER;
  9          G_NUM_RESULT_CACHE NUMBER := 0;
 10          G_NUM_NO_RESULT_CACHE NUMBER := 0;
 11  END;
 12  /

Package created.

SQL> CREATE OR REPLACE
  2    PACKAGE BODY PKG1
  3      IS
  4          FUNCTION F_RESULT_CACHE
  5            RETURN NUMBER
  6            RESULT_CACHE
  7            IS
  8            BEGIN
  9                G_NUM_RESULT_CACHE := G_NUM_RESULT_CACHE + 1;
 10                DBMS_OUTPUT.PUT_LINE('F_RESULT_CACHE');
 11                RETURN G_NUM_RESULT_CACHE;
 12          END;
 13          FUNCTION F_NO_RESULT_CACHE
 14            RETURN NUMBER
 15            IS
 16            BEGIN
 17                G_NUM_NO_RESULT_CACHE := G_NUM_NO_RESULT_CACHE + 1;
 18                DBMS_OUTPUT.PUT_LINE('F_NO_RESULT_CACHE');
 19                RETURN G_NUM_NO_RESULT_CACHE;
 20          END;
 21  END;
 22  /

Package body created.

SQL> SET SERVEROUTPUT ON
SQL> SELECT  PKG1.F_RESULT_CACHE,
  2          PKG1.F_NO_RESULT_CACHE
  3    FROM  EMP
  4  /

F_RESULT_CACHE F_NO_RESULT_CACHE
-------------- -----------------
             1                 1
             1                 2
             1                 3
             1                 4
             1                 5
             1                 6
             1                 7
             1                 8
             1                 9
             1                10
             1                11

F_RESULT_CACHE F_NO_RESULT_CACHE
-------------- -----------------
             1                12
             1                13
             1                14

14 rows selected.

F_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
F_NO_RESULT_CACHE
SQL> EXEC DBMS_OUTPUT.PUT_LINE('G_NUM_RESULT_CACHE = ' || PKG1.G_NUM_RESULT_CACHE)
G_NUM_RESULT_CACHE = 1

PL/SQL procedure successfully completed.

SQL> EXEC DBMS_OUTPUT.PUT_LINE('G_NUM_NO_RESULT_CACHE = ' || PKG1.G_NUM_NO_RESULT_CACHE)
G_NUM_NO_RESULT_CACHE = 14

PL/SQL procedure successfully completed.

SQL> 



Так-что хочешь-не-хочешь а лучше удостовериться ф-ция детерминистик (в действительности).

SY.
...
Рейтинг: 0 / 0
функция и в select-листе и в where
    #39596478
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Leonid Kudryavtsev"Oracle умный" и вычислив обычные выражения, функцию и трогать не будетобычно по дефолту так и будет, т.к. оракл старается предикаты с функциями перемещать в конец всего FILTER:
Код: 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.
SQL> create or replace function f1(x int) return int as
  2  begin
  3     return x;
  4  end;
  5  /

Function created.

SQL> create or replace function f2(x int) return int as
  2  begin
  3     return x;
  4  end;
  5  /

Function created.

SQL> create table test as
  2    select level a, level b, level c from dual connect by level<=1000;

Table created.

SQL> call dbms_stats.gather_table_stats('','test');

Call completed.

SQL> explain plan for
  2  select *
  3  from test
  4  where f1(a) > :z1 and a > :z1 and f2(a) > :z1
  5    and f1(b) > :z1 and b > :z1 and f2(b) > :z1
  6    and f1(c) > :z1 and c > :z1 and f2(c) > :z1
  7  /

Explained.

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
Plan hash value: 1357081020

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    12 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST |     1 |    12 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("A">TO_NUMBER(:Z1) AND "B">TO_NUMBER(:Z1) AND
              "C">TO_NUMBER(:Z1) AND "F1"("A")>TO_NUMBER(:Z1) AND
              "F2"("A")>TO_NUMBER(:Z1) AND "F1"("B")>TO_NUMBER(:Z1) AND
              "F2"("B")>TO_NUMBER(:Z1) AND "F1"("C")>TO_NUMBER(:Z1) AND
              "F2"("C")>TO_NUMBER(:Z1))

17 rows selected.


Но по-хорошему, ораклу надо дать статистику функции с помощью associate statistics
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / функция и в select-листе и в where
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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