powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Смена плана с INDEX на NATURAL при соед-нии небольшого числа строк
6 сообщений из 6, страница 1 из 1
Смена плана с INDEX на NATURAL при соед-нии небольшого числа строк
    #38749183
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hi all.

LI-T3.0.0.31309

Чё-то не просеку, как такое может быть.
Имеется две таблички:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
recreate table rrr (
    snd  bigint,
    rcv  bigint
);
alter table rrr add constraint rrr_unq unique (snd, rcv) using index rrr_snd_rcv_unq;
commit;

recreate table qqq (
    id      bigint not null,
    snd  bigint,
    rcv  bigint,
    sid  bigint
);
commit;
alter table qqq add constraint pk_qqq primary key (id);
create descending index qqq_snd_rcv_sid_desc on qqq (snd, rcv, sid);
commit;

И вот такой блок, выводящий план соединения:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
set planonly;
set term ^;
execute block as 
  declare r int;
  declare k int;
begin
  select 1 from qqq qd join rrr r on  qd.snd = r.snd and qd.rcv = r.rcv where qd.sid = :r  into k;
end
^ set term ;^
set planonly;

Оказывается, план этот будет благоприятным ( JOIN (R NATURAL, QD INDEX (QQQ_SND_RCV_SID_DESC)) ) - только при превышении в таблице QQQ числа строк некоторого порога. Причём, порог этот вроде бы как... "слегка переменный" :-)
Если же число строк в QQQ невелико, то план сменится на QD NATURAL.

Вот полный DDL + test:
Код: 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.
set plan off;
set term ^;
execute block as begin
  begin execute statement 'create sequence ggg'; when any do begin end end
end
^set term ;^
commit;
alter sequence ggg restart with 0;

recreate table rrr (
    snd  bigint,
    rcv  bigint
);
commit;

insert into rrr (snd, rcv) values (null, 1000);
insert into rrr (snd, rcv) values (1000, 1200);
insert into rrr (snd, rcv) values (1200, 2000);
insert into rrr (snd, rcv) values (1000, 3300);
insert into rrr (snd, rcv) values (2000, 3300);
insert into rrr (snd, rcv) values (2100, 3300);
insert into rrr (snd, rcv) values (3300, null);
commit;

alter table rrr add constraint rrr_unq unique (snd, rcv) using index rrr_snd_rcv_unq;
create index rrr_rcvop on rrr (rcv);
commit;

recreate table qqq (
    id      bigint not null,
    snd  bigint,
    rcv  bigint,
    sid  bigint
);
commit;

-- start rows:
insert into qqq (id, snd, sid, rcv) values (gen_id(ggg,1), 1000, 1200, 22);
insert into qqq (id, snd, sid, rcv) values (gen_id(ggg,1), 1000, 1200, 24);
insert into qqq (id, snd, sid, rcv) values (gen_id(ggg,1), 1000, 3300, 24);

-- addi rows:
 insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*99999 from rdb$types,rdb$types rows 17;  -- starts using index from 18, stat=0.04761904850602150
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*999 from rdb$types,rdb$types rows 17; -- starts using index from 18, stat=0.04761904850602150
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*99 from rdb$types,rdb$types rows 17; -- starts using index from 18, stat=0.05000000074505806
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*49 from rdb$types,rdb$types rows 17; -- starts using index from 18, stat=0.05263157933950424
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*19 from rdb$types,rdb$types rows 20; -- starts using index from 20, stat=0.05882352963089943
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*9  from rdb$types,rdb$types rows 24; -- starts using index from 24, stat=0.07692307978868485
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*5  from rdb$types,rdb$types rows 32; -- starts using index from 33, stat=0.1111111119389534
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*4  from rdb$types,rdb$types rows 38; -- starts using index from 39, stat = 0.1250000000000000
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*3  from rdb$types,rdb$types rows 52; -- starts using index from 53, stat=0.1428571492433548
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*2  from rdb$types,rdb$types rows 92; -- starts using index from 93, stat=0.1666666716337204
-- insert into qqq select gen_id(ggg,1), 1000, 3300, rand()*1  from rdb$types,rdb$types rows 65000; --> no use index at all
 
commit;
alter table qqq add constraint pk_qqq primary key (id);
create descending index qqq_snd_rcv_sid_desc on qqq (snd, rcv, sid);
commit;
SET STATISTICS INDEX QQQ_SND_RCV_SID_DESC;
COMMIT;
-----------------

-----------------
set width idx 25;
set width fld 10;
select
    ri.rdb$index_name idx
    ,ri.rdb$statistics ri_stat
    ,ri.rdb$segment_count seg_cnt
    ,rs.rdb$field_name fld
    ,rs.rdb$field_position pos
    ,rs.rdb$statistics rs_stat
from rdb$indices ri
join rdb$index_segments rs using (rdb$index_name)
where ri.rdb$index_name = 'QQQ_SND_RCV_SID_DESC';

-------------------

set planonly;
set term ^;
execute block as 
  declare r int;
  declare k int;
begin
  select 1 from qqq qd join rrr r on qd.snd = r.snd and qd.rcv = r.rcv where qd.sid = :r into k;
end
^ set term ;^
set planonly;

В нём выделены жирным шрифтом стейтменты, которые применялись (по-одному) к таблице QQQ.

Чем объяснить, что ФБ не юзает индекс по QQQ при числе строк в ней менее 3 ("start rows") + 18 (с рандомами в третьем поле и не изменяемыми "префиксами" в первом и втором полях) ?
...
Рейтинг: 0 / 0
Смена плана с INDEX на NATURAL при соед-нии небольшого числа строк
    #38751020
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидЧем объяснить, что ФБ не юзает индекс по QQQ при числе строк в ней менее 3 ("start rows") + 18 (с рандомами в третьем поле и не изменяемыми "префиксами" в первом и втором полях) ?
стоимостной оценкой, очевидно. Твое мнение не совпадает с мнением оптимизатора.
...
Рейтинг: 0 / 0
Смена плана с INDEX на NATURAL при соед-нии небольшого числа строк
    #38751043
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitr,

а кто-то когда-то тут говорил, что "если есть индекс, то он *будет* использоваться. точка" (цитирую по памяти).
Или для малых таблиц это не действует ?
...
Рейтинг: 0 / 0
Смена плана с INDEX на NATURAL при соед-нии небольшого числа строк
    #38751044
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
насколько вижу из метаданных, варианта планов тут два:

1) JOIN (R NATURAL, QD INDEX (QQQ_SND_RCV_SID_DESC))
2) JOIN (QD NATURAL, R INDEX (RRR_SND_RCV_UNQ))

где тут "индекс не используется"? Или у тебя другие планы?
...
Рейтинг: 0 / 0
Смена плана с INDEX на NATURAL при соед-нии небольшого числа строк
    #38751049
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrнасколько вижу из метаданных, варианта планов тут два:

1) JOIN (R NATURAL, QD INDEX (QQQ_SND_RCV_SID_DESC))
2) JOIN (QD NATURAL, R INDEX (RRR_SND_RCV_UNQ))

где тут "индекс не используется"? Или у тебя другие планы?Ну так в обоих случаях вижу 'NATURAL'.
И хрен бы с этой 'RRR', но вот про 'QQQ' какая-то тревога закрадывается... :-)
...
Рейтинг: 0 / 0
Смена плана с INDEX на NATURAL при соед-нии небольшого числа строк
    #38751052
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидНу так в обоих случаях вижу 'NATURAL'.
для ведущей таблицы, будь она QQQ или RRR, в этом запросе невозможно использовать индекс. А для ведомой он используется в обоих случаях. К чему именно претензии? Вынеси SID из композита в отдельный индекс, тогда и получишь "конфетку".

ТаблоидИ хрен бы с этой 'RRR', но вот про 'QQQ' какая-то тревога закрадывается... :-)
порядок джойна определяется в том числе размером таблиц. И ты это явно обязан знать.
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Смена плана с INDEX на NATURAL при соед-нии небольшого числа строк
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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