Поведение индекса на основе функций, когда функция зависит от данных из другой (не той, по которой был создан индекс) таблицы - PullRequest
2 голосов
/ 17 апреля 2019

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

Предположим, у меня есть следующие тестовые данные:

SQL> drop table table_with_data;
   2 drop table table_test_a;
   3 drop table table_test_b;
   4
   5 create table table_with_data (data_id integer, val1 number);
   6 create table table_test_a (val1 number, val2 varchar2(100));
   7 create table table_test_b (val1 number, val2 varchar2(100));
   8
   9 insert into table_with_data values (1,1);
  10 insert into table_with_data values (10,2);
  11 insert into table_with_data values (30,3);
  12
  13 insert into table_test_b values (1, 'one');
  14 insert into table_test_b values (20, 'two');
  15 insert into table_test_b values (30, 'three');
  16
  17 insert into table_test_a values (1, 'first');
  18 insert into table_test_a values (2, 'second');
  19 insert into table_test_a values (3, 'third');

Также я определил функцию:

SQL> create or replace function test_func(val_in number) 
   2 return number deterministic as
   3 output number;
   4  begin 
   5   select val1 
   6   into output
   7   from table_with_data
   8   where data_id = val_in;
   9
  10   return output;
  11  end;

Чтобы ускорить такой запрос

SQL> select a.*, (select b.val2 
   2              from table_test_b b
   3              where test_func(b.val1) = a.val1)
   4  from table_test_a a;

IВы решили использовать индекс на основе функций

SQL> create index test_func_indx on table_test_b(test_func(val1));

И он работает нормально.

Но если кто-то обновит значение в table_with_data

SQL> update table_with_data set data_id = 20 where val1 = 2;

Вывод вышеупомянутого запроса не изменится.

Существует ли какой-либо правильный способ обновления индекса на основе функцииесли функция зависит от данных из другой таблицы?

Или, может быть, есть другие способы построения индекса на основе функции в этом случае?

1 Ответ

2 голосов
/ 17 апреля 2019

Индексируются только функции, которые всегда возвращают один и тот же результат для одних и тех же параметров - детерминированные функции. Вот почему обновление индекса на основе функций, если функция зависит от данных из другой таблицы, недопустимо и равно нулю. Помимо того, что PostgreSQL и база данных Oracle требуют, чтобы при использовании индекса они объявляли функции детерминированными, поэтому необходимо использовать ключевое слово DETERMINISTIC (Oracle) или IMMUTABLE (PostgreSQL).

но если вы обновите table_with_data, он больше не будет детерминированным

update table_with_data set data_id = 1 where val1 = 2; 

и oracle не допускает индекс недетерминированных функций для пользовательских функций.

...