Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / where not exists сильно тормозит / 25 сообщений из 48, страница 1 из 2
05.03.2020, 11:01
    #39934510
ArtDen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
Приветствую.

Есть много запросов такого типа:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
delete from utable
where not exists (
  select 1 
  from table1 t1
  join table2 t2 join t1
  join table3 t3 join t2

  where utable.fld1 = t1.fld1
  and utable.fld2 = t2.fld2
  and utable.fld3 = t3.fld3
)



Если delete заменить на select *, то сути это не изменит. Так вот, запросы эти дико тормозят (выполняются более чем суток, потом я их прибиваю). По каждому полю каждой таблицы, которые участвуют в where вложенного запроса есть fk-индекс + у utable стоит unique на все поля. У полей, которые участвуют в join-е, есть pk- и fk- индексы.
Примерное количество записей в таблицах: utable ~25000, в наибольшей table* ~5 млн. Все поля в запросе - integer

Статистика индексов посчитана. В какую сторону копать? Если надо, выложу реальные ddl и запросы.

PS: Система работает с разными СУБД. На тех же данных (но без fk-индексов) последний постгрес отрабатывает менее чем за 10 секунд на не разогретой базе. Надо что-то придумать, чтобы чтобы FB не сильно от него отставал.

PPS: FB 2.5.8.27089 x64, 10я винда

PPPS: если переписать запрос на right join с where is null, то ситуация не улучшается.
...
Рейтинг: 0 / 0
05.03.2020, 11:10
    #39934517
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen,

я так понимаю запрос совсем не реальный, ибо условий соединения в join нет.

NOT EXISTS плохо оптимизируется, HASH OUTER JOIN у нас пока нет
...
Рейтинг: 0 / 0
05.03.2020, 11:28
    #39934533
pastor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen,

5 млн - это не сутки, в любом случае.

иногда делаю

Код: sql
1.
2.
3.
4.
5.
6.
for select t1.ID 
     from t1
             join t2 on t2.ID_T1 = t1.ID
    where t2.ID is null
    into :ID1
    do delete from t1 where ID = :ID1;



PS можно через курсор WHERE OF
...
Рейтинг: 0 / 0
05.03.2020, 11:38
    #39934540
WildSery
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
pastor
иногда делаю
LEFT
...
Рейтинг: 0 / 0
05.03.2020, 11:47
    #39934560
Ivan_Pisarevsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
можно пример хоть маленько приближенный к реальным метаданным?
...
Рейтинг: 0 / 0
05.03.2020, 12:30
    #39934592
pastor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
WildSery
pastor
иногда делаю
LEFT


mea culpa, mea maxima culpa

конечно же LEFT
...
Рейтинг: 0 / 0
05.03.2020, 14:10
    #39934669
ArtDen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
Ivan_Pisarevsky, Поубирал из ddl-ля поля, которые не участвуют в запросе, но всё равно много получается. Вот такое удаление выполняется почти сутки (скоро буду прибивать):

Код: 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.
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.
create table ws_database(
	id         integer not null,

	constraint pk_ws_database_id primary key (id)
);

create table files(
	id            integer not null,
	db_id         integer,

	constraint pk_files_id    primary key (id),
	constraint fk_files_db_id foreign key (db_id) references ws_database(id)  on delete cascade
);


create table history_user (
	id_user integer not null,
	name    varchar(240),

	constraint pk_history_user     primary key (id_user),
	constraint u_history_user_name unique      (name)
);

create table history_comp (
	id_comp integer not null,
	name    varchar(240),

	constraint pk_history_comp     primary key (id_comp),
	constraint u_history_comp_name unique      (name)
);

create table table_names(
	id   integer not null,
	name varchar(128) not null,

	constraint pk_table_names_id  primary key (id),
	constraint u_table_names_name unique      (name)
);


create table history_table (
	id_table integer not null,
	id_file  integer not null,
	id_name  integer not null,

	constraint pk_history_table_id_table  primary key (id_table),
	constraint fk_history_table_id_file   foreign key (id_file) references files(id) on delete cascade,
	constraint fk_history_table_id_name   foreign key (id_name) references table_names(id),
	constraint u_history_table            unique      (id_file,id_name)
);

create table history_row (
	id_row   integer not null,
	id_table integer not null,
	keystr   varchar(2048),

	constraint pk_history_row_id_row   primary key (id_row),
	constraint fk_history_row_id_table foreign key (id_table) references history_table(id_table) on delete cascade
);

create table history (
	id_rec     integer default -1 not null,
	id_row     integer not null,
	id_module  integer not null,
	id_user    integer not null,
	id_comp    integer not null,
	id_array   integer not null,
	id_col     integer not null,
	modifytype integer not null,
	datetime   timestamp not null,

	constraint pk_history           primary key (id_rec),
	constraint fk_history_id_row    foreign key (id_row)    references history_row   (id_row) on delete cascade,
	constraint fk_history_id_user   foreign key (id_user)   references history_user  (id_user),
	constraint fk_history_id_comp   foreign key (id_comp)   references history_comp  (id_comp)
);

create table fast_history (
	db_id    integer not null,
	tname_id integer not null,
	id_user  integer not null,
	id_comp  integer not null,

	constraint fk_fast_history_dbid foreign key (db_id)   references ws_database  (id) on delete cascade,

	constraint fk_fast_history_tn   foreign key (tname_id) references table_names  (id),
	constraint fk_fast_history_user foreign key (id_user)  references history_user (id_user),
	constraint fk_fast_history_comp foreign key (id_comp)  references history_comp (id_comp),
	constraint u_fast_history       unique      (db_id,tname_id,id_user,id_comp)
);

commit;

delete from fast_history 
where not exists( 
	select 1 
	from history h 
	join history_row r on h.id_row = r.id_row 
	join history_table t on t.id_table = r.id_table 
	join files f on f.id = t.id_file 
	where f.db_id = fast_history.db_id 
	and t.id_name = fast_history.tname_id 
	and h.id_user = fast_history.id_user 
	and h.id_comp = fast_history.id_comp 
);



Количество записей history - 5 млн, fast_history - 25000, history_row - 1.5 млн, history_table - 400 тыс, files - 60тыс. Остальные - несколько десятков
...
Рейтинг: 0 / 0
05.03.2020, 14:17
    #39934675
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen,

план запроса какой?
...
Рейтинг: 0 / 0
05.03.2020, 15:05
    #39934698
ArtDen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
kdv,

PLAN JOIN (JOIN (H INDEX (FK_HISTORY_IDCOMP, FK_HISTORY_IDUSER), JOIN (T INDEX (FK_HISTORYTABLE_IDNAME), F INDEX (PK_FILES_ID))), R INDEX (PK_HISTORYROW_IDROW))
PLAN (FAST_HISTORY NATURAL)
...
Рейтинг: 0 / 0
05.03.2020, 15:15
    #39934711
m7m
m7m
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen
kdv,

PLAN JOIN (JOIN (H INDEX (FK_HISTORY_IDCOMP, FK_HISTORY_IDUSER), JOIN (T INDEX (FK_HISTORYTABLE_IDNAME), F INDEX (PK_FILES_ID))), R INDEX (PK_HISTORYROW_IDROW))
PLAN (FAST_HISTORY NATURAL)


А сколько различных значений
у ID_USER и ID_COMP
????
...
Рейтинг: 0 / 0
05.03.2020, 15:15
    #39934712
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDenPLAN (FAST_HISTORY NATURAL)
так я и знал! Ну, значит, вложенный запрос выполняется 25 тысяч раз.
...
Рейтинг: 0 / 0
05.03.2020, 15:19
    #39934715
m7m
m7m
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
kdv
ArtDenPLAN (FAST_HISTORY NATURAL)

так я и знал! Ну, значит, вложенный запрос выполняется 25 тысяч раз.

А что тут можно было ожидать чего-то другого
...
Рейтинг: 0 / 0
05.03.2020, 15:20
    #39934717
ArtDen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
m7m,

900 и 1200

Получается, я ошибся. В остальных справочных таблицах не несколько десятков, в несколько сотен записей.
...
Рейтинг: 0 / 0
05.03.2020, 15:24
    #39934720
ArtDen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
В общем, нужны рекомендации. При необходимости могу немного поменять структуру базы, если другими способами невозможно что либо сделать.

PS: SQL-запрос должен быть без расширений FB, чтобы он отрабатывал на других СУБД
...
Рейтинг: 0 / 0
05.03.2020, 15:25
    #39934721
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen,

тут ничего удивительного. Как я уже говорил HASH OUTER JOIN ФБ пока не умеет. Ты ещё и дополнительный геморрой себе отрастил тем, что не сделал искусственный ПК в fast_history. Если бы он был можно было бы повоевать вот так


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
delete from fast_history fh1
where not exists( 
	select 1 
	from history h 
	join history_row r on h.id_row = r.id_row 
	join history_table t on t.id_table = r.id_table 
	join files f on f.id = t.id_file 
        join fast_history fh2 on
	    f.db_id = fh2.db_id and 
            t.id_name = fh2.tname_id and
	    h.id_user = fh2.id_user and
	    h.id_comp = fh2.id_comp 
       where fh2.id = fh1.id
);



не факт что было бы быстрее, но мало ли.

Вот это

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
	select count(*) 
	from history h 
	join history_row r on h.id_row = r.id_row 
	join history_table t on t.id_table = r.id_table 
	join files f on f.id = t.id_file 
        join fast_history fh2 on
	    f.db_id = fh2.db_id and 
            t.id_name = fh2.tname_id and
	    h.id_user = fh2.id_user and
	    h.id_comp = fh2.id_comp 



сколько выполняется?
...
Рейтинг: 0 / 0
05.03.2020, 15:46
    #39934739
ArtDen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
Симонов Денис
сколько выполняется?

Ждал почти 20 минут. Не дождался, прибил.
...
Рейтинг: 0 / 0
05.03.2020, 15:57
    #39934749
m7m
m7m
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen
m7m,

900 и 1200


и получается около 5000 дубликатов в таблице history на каждое значение
и вот этот кусок
H INDEX (FK_HISTORY_IDCOMP, FK_HISTORY_IDUSER)
совсем не вселяет оптимизма

Возможно чуток может помочь избавление в плане от одного из этих индексов
Возможно немного больше поможет составной индекс ID_COMP,ID_USER
...
Рейтинг: 0 / 0
05.03.2020, 16:07
    #39934756
m7m
m7m
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
Симонов Денис
Вот это

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
	select count(*) 
	from history h 
	join history_row r on h.id_row = r.id_row 
	join history_table t on t.id_table = r.id_table 
	join files f on f.id = t.id_file 
        join fast_history fh2 on
	    f.db_id = fh2.db_id and 
            t.id_name = fh2.tname_id and
	    h.id_user = fh2.id_user and
	    h.id_comp = fh2.id_comp 




сколько выполняется?

Денис возможно все-же время выполнения этого запроса
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
	select 1 
	from history h 
	join history_row r on h.id_row = r.id_row 
	join history_table t on t.id_table = r.id_table 
	join files f on f.id = t.id_file 
	where f.db_id = :Fast_history_db_id 
	and t.id_name = :Fast_history_tname_id 
	and h.id_user = :Fast_history_id_user 
	and h.id_comp = :Fast_history_id_comp 


более интересно
тем более что именно его и надо оптимизировать
Хотя что тут интересного по сообщениям и так ясно что он тормозит
...
Рейтинг: 0 / 0
05.03.2020, 16:10
    #39934760
ArtDen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
m7m,

1. Запустил
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
delete from fast_history 
where not exists( 
	select 1 
	from history h 
	join history_row r on h.id_row = r.id_row 
	join history_table t on t.id_table = r.id_table 
	join files f on f.id = t.id_file 
	where f.db_id = fast_history.db_id 
	and t.id_name = fast_history.tname_id 
	and h.id_user+0 = fast_history.id_user 
	and h.id_comp+0 = fast_history.id_comp 
)


Жду. +0 в правильном месте?
План получился
PLAN JOIN (JOIN (JOIN (T INDEX (FK_HISTORYTABLE_IDNAME), F INDEX (PK_FILES_ID)), R INDEX (FK_HISTORYROW_IDTABLE)), H INDEX (FK_HISTORY_IDROW))
PLAN (FAST_HISTORY NATURAL)

2. Составными индексами уже наигрался. Они дали выигрыш в других запросах с меньшим количеством join. Могу ещё раз попробовать.
...
Рейтинг: 0 / 0
05.03.2020, 16:17
    #39934768
ArtDen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
m7m

Денис возможно все-же время выполнения этого запроса
более интересно
тем более что именно его и надо оптимизировать
Хотя что тут интересного по сообщениям и так ясно что он тормозит

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
	select 1 
	from history h 
	join history_row r on h.id_row = r.id_row 
	join history_table t on t.id_table = r.id_table 
	join files f on f.id = t.id_file 
	where f.db_id = (select first 1 DB_ID from FAST_HISTORY)
	and t.id_name = (select first 1 TNAME_ID from FAST_HISTORY)
	and h.id_user = (select first 1 ID_USER from FAST_HISTORY)
	and h.id_comp = (select first 1 ID_COMP from FAST_HISTORY)



0.03 sec
...
Рейтинг: 0 / 0
05.03.2020, 16:38
    #39934780
m7m
m7m
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen
m7m

Денис возможно все-же время выполнения этого запроса
более интересно
тем более что именно его и надо оптимизировать
Хотя что тут интересного по сообщениям и так ясно что он тормозит

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
	select 1 
	from history h 
	join history_row r on h.id_row = r.id_row 
	join history_table t on t.id_table = r.id_table 
	join files f on f.id = t.id_file 
	where f.db_id = (select first 1 DB_ID from FAST_HISTORY)
	and t.id_name = (select first 1 TNAME_ID from FAST_HISTORY)
	and h.id_user = (select first 1 ID_USER from FAST_HISTORY)
	and h.id_comp = (select first 1 ID_COMP from FAST_HISTORY)




0.03 sec


План какой?
...
Рейтинг: 0 / 0
05.03.2020, 17:39
    #39934836
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen,

чую у вас в мусор в fast_history накопился при неудачных удалениях


Код: sql
1.
select count(*) from fast_history




А потом оптимизировать надо, а не сам delete

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select count(*) from fast_history 
where not exists( 
	select 1 
	from history h 
	join history_row r on h.id_row = r.id_row 
	join history_table t on t.id_table = r.id_table 
	join files f on f.id = t.id_file 
	where f.db_id = fast_history.db_id 
	and t.id_name = fast_history.tname_id 
	and h.id_user = fast_history.id_user 
	and h.id_comp = fast_history.id_comp 
)
...
Рейтинг: 0 / 0
05.03.2020, 18:31
    #39934868
m7m
m7m
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen
0.03 sec


25000 * 0.03 /60=12.5 минут
ну пусть 15 минут
что-то у меня в голове не складывается
может быть действительно
Симонов Денис
чую у вас в мусор в fast_history накопился при неудачных удалениях
...
Рейтинг: 0 / 0
05.03.2020, 19:11
    #39934884
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
ArtDen,

gstat -r -t fast_history

?
...
Рейтинг: 0 / 0
05.03.2020, 19:24
    #39934896
ArtDen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
where not exists сильно тормозит
Вот
Код: plaintext
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.
Database header page information:
	Flags			0
	Checksum		12345
	Generation		130468
	Page size		16384
	ODS version		11.2
	Oldest transaction	130452
	Oldest active		130453
	Oldest snapshot		130448
	Next transaction	130458
	Bumped transaction	1
	Sequence number		0
	Next attachment ID	111
	Implementation ID	26
	Shadow count		0
	Page buffers		0
	Next header page	0
	Database dialect	3
	Creation date		Feb 29, 2020 17:18:29
	Attributes		

    Variable header data:
	*END*


Database file sequence:
File E:\PrimeDbFirebirdDatabase\PRIME1.FBDB is the only file

Analyzing database pages ...
FAST_HISTORY (220)
    Primary pointer page: 613, Index root page: 614
    Average record length: 21.00, total records: 24945
    Average version length: 0.00, total versions: 0, max versions: 0
    Data pages: 95, data page slots: 95, average fill: 61%
    Fill distribution:
	 0 - 19% = 0
	20 - 39% = 1
	40 - 59% = 0
	60 - 79% = 94
	80 - 99% = 0

    Index FK_FASTHISTORY_DBID (0)
	Depth: 2, leaf buckets: 7, nodes: 24945
	Average data length: 0.00, total dup: 24929, max dup: 20405
	Fill distribution:
	     0 - 19% = 1
	    20 - 39% = 0
	    40 - 59% = 0
	    60 - 79% = 0
	    80 - 99% = 6

    Index FK_FASTHISTORY_IDCOMP (3)
	Depth: 2, leaf buckets: 10, nodes: 24945
	Average data length: 0.09, total dup: 23730, max dup: 295
	Fill distribution:
	     0 - 19% = 1
	    20 - 39% = 0
	    40 - 59% = 4
	    60 - 79% = 3
	    80 - 99% = 2

    Index FK_FASTHISTORY_IDUSER (2)
	Depth: 2, leaf buckets: 9, nodes: 24945
	Average data length: 0.07, total dup: 24018, max dup: 1375
	Fill distribution:
	     0 - 19% = 0
	    20 - 39% = 0
	    40 - 59% = 2
	    60 - 79% = 5
	    80 - 99% = 2

    Index FK_FASTHISTORY_TNAMEID (1)
	Depth: 2, leaf buckets: 8, nodes: 24945
	Average data length: 0.10, total dup: 23224, max dup: 1509
	Fill distribution:
	     0 - 19% = 0
	    20 - 39% = 0
	    40 - 59% = 0
	    60 - 79% = 5
	    80 - 99% = 3

    Index U_FASTHISTORY_DBID_IDCOMP_I (4)
	Depth: 2, leaf buckets: 17, nodes: 24945
	Average data length: 2.37, total dup: 0, max dup: 0
	Fill distribution:
	     0 - 19% = 0
	    20 - 39% = 0
	    40 - 59% = 8
	    60 - 79% = 8
	    80 - 99% = 1



Данные свежезагруженные. Реально в таблице FAST_HISTORY нету данных для удаления. Т.е. запрос должен отработать вхолостую.
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / where not exists сильно тормозит / 25 сообщений из 48, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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