Гость
Map
Форумы / Informix [игнор отключен] [закрыт для гостей] / Производительность запросов с Set / 7 сообщений из 7, страница 1 из 1
23.09.2016, 14:57
    #39314370
falcon111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность запросов с Set
Делаю вычисления с пересечением множеств.
Проходят вычисления по таблице, обновляются-добавляются-удаляются записи, в конце по этой же таблице надо смотреть какие записи не попали в обработку, и выдать по ним упоминания в лог ошибок.

Делалось так: Идет обработка таблицы, ид обработанных записей заносятся в set (integer not null), под конец делается
select id from maintable where id not in table(setvariable) - это выдает ид подвисших записей.
Все бы хорошо, но выполнение конкретно этого запроса занимало десятки секунд. как я там ни изгалялся - ничего не помогало.

Переделал на создание временной таблицы с одним полем с ид
При обработке основной таблицы вместо сета идшники заносятся в эту таблицу,
Для вычисления пересечения создаю вторую временную таблицу, в нее insert всех ид из основной таблицы, затем delete из нее where id in (select id from temptable1)
Это - отрабатывает за доли секунды, хотя на первый взгляд работы серверу больше - во первых копируются ВСЕ ид основной таблицы, потом из нее удаляются ид обработанных записей... А работает быстро.

Объясните почему такая хрень?

Сервер 12.10fc6
Спасибо.
...
Рейтинг: 0 / 0
25.09.2016, 11:29
    #39315074
АнатоЛой
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность запросов с Set
falcon111, как насчёт мысли, что всё дело в индекса и оптимизаторе? В каком случае есть индексы и какие? Какие планы делает оптимизатор в обоих случаях?
...
Рейтинг: 0 / 0
26.09.2016, 20:22
    #39315910
falcon111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность запросов с Set
АнатоЛой,

Доступа к файловой системе сервера в данный момент у меня нет, эксплейн не посмотрю.

Вот код:
Код: 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.
drop procedure if exists test_performance_issues;
create procedure test_performance_issues(Method integer) returning varchar(32) as ExecTime;
  define b      bigint;
  define d      double precision;
  define x,v    integer;
  define rc     varchar(32);
  define s      set (integer not null);

  begin
    on exception in (-206)
      create temp table tmp_test_main_data (
        RecId integer primary key
      ) with no log;
      update statistics low for table tmp_test_main_data;
    end exception with resume;
    delete from tmp_test_main_data;
  end;

  for x=1 to 5000
    insert into tmp_test_main_data(RecId) values(x);
  end for;

  if Method==1 then
    let x=1;
    foreach select m.RecId
            into   v
            from tmp_test_main_data m
      insert into table(s) values(v);
      if x==4000 then exit foreach; end if;
      let x=x+1;
    end foreach;
    let b=GetHiResTimer_Start();
    select count(*) into v from tmp_test_main_data m where m.RecId NOT in s;
    let d=GetHiResTimer_Finish(b);
  else
    begin 
    on exception in (-206)
      create temp table tmp_test_intersection (
        RecId integer
      ) with no log;
      update statistics low for table tmp_test_intersection;
      end exception with resume;
      delete from tmp_test_intersection;
    end;
    let x=1;
    foreach select m.RecId
            into   v
            from tmp_test_main_data m
      insert into tmp_test_intersection(RecId) values(v);
      if x==4000 then exit foreach; end if;
      let x=x+1;
    end foreach;
    let b=GetHiResTimer_Start();
    select count(*) into v from tmp_test_Main_Data m where m.RecId NOT in (select i.RecId from tmp_test_intersection i);
    let d=GetHiResTimer_Finish(b);
  end if;
  let d=GetHiResTimer_Finish(b);
  let rc=(d/1000)::numeric(6,3)||'s, '||v||' recs';

  return rc;
end procedure;

update statistics for procedure test_performance_issues;

execute procedure test_performance_issues(1);
execute procedure test_performance_issues(2);

drop procedure test_performance_issues;



Вот результат:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Successfully connected to tb as user informix.
Procedure successfully dropped.
Procedure successfully created.
Statistics successfully updated.
exectime
--------------------------------
1.575s, 1000 recs
1 rows selected.
exectime
--------------------------------
0.031s, 1000 recs
1 rows selected.
Procedure successfully dropped.



Откуда такая разница?
...
Рейтинг: 0 / 0
27.09.2016, 00:27
    #39315962
АнатоЛой
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность запросов с Set
falcon111, зуб даю, оптимизатор выдал разные планы запросов. В случае с временной таблицей вряд ли он делает 4000 поисков по ключу, но вот пересечение с индексом первичного ключа - запросто. А в случае с множеством - банальных 5000 переборов. Это и по времени видно...
...
Рейтинг: 0 / 0
27.09.2016, 01:40
    #39315968
falcon111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность запросов с Set
АнатоЛой,

То, что план разный строит, это очевидно, потом как смогу гляну план выполнения, я просто думал, может есть какие-то тонкости/рекомендации с использованием СЕТов...

Апофеоз.
В моем примере:
Код: sql
1.
select count(*) into v from tmp_test_main_data m where m.RecId NOT in s;

Это ^ выполняется полторы секунды.

Код: sql
1.
select count(*) into v from tmp_test_main_data m where m.RecId NOT in (select * from table(s));

А вот это ^ три сотых секунды.

Если я не прав - объясните в чем, мне пока мыслится это косяком сервера.
Радует только что причину непонятных тупняков я нашел.
...
Рейтинг: 0 / 0
27.09.2016, 15:26
    #39316298
Daugava
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность запросов с Set
Рекомендация одна - стараться не использовать переменньіх для запросов в процедурах.
...
Рейтинг: 0 / 0
27.09.2016, 18:57
    #39316509
falcon111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность запросов с Set
Daugava,

Надежда что в FC7 станет лучше не оправдалась. Все осталось как же, как было.
Исключение только в том что все-таки результат с сетом стал оптимальным.

Код: sql
1.
select count(*) into v from tmp_test_main_data m where m.RecId NOT in (select * from table(s));

дает теперь 0.019s, 1000 recs

Код: sql
1.
select count(*) into v from tmp_test_Main_Data m where m.RecId NOT in (select i.RecId from tmp_test_intersection i);

а это на треть медленнее: 0.030s, 1000 recs

Для себя вопрос считаю исчерпанным.
...
Рейтинг: 0 / 0
Форумы / Informix [игнор отключен] [закрыт для гостей] / Производительность запросов с Set / 7 сообщений из 7, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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