Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Где мой Nested Loop %) / 25 сообщений из 25, страница 1 из 1
07.09.2005, 19:38
    #33257392
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Код: 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.
CREATE TABLE table1 (
    t1_id serial NOT NULL,
    t1_val integer NOT NULL
);

ALTER TABLE ONLY table1
    ADD CONSTRAINT table1_pkey PRIMARY KEY (t1_id);

CREATE TABLE table2 (
    t2_id serial NOT NULL,
    t2_t1_id integer NOT NULL,
    t2_val integer NOT NULL
);

ALTER TABLE ONLY table2
    ADD CONSTRAINT table2_pkey PRIMARY KEY (t2_id);

INSERT INTO table1 (t1_id, t1_val) VALUES ( 1 ,  10 );
INSERT INTO table1 (t1_id, t1_val) VALUES ( 2 ,  20 );
INSERT INTO table1 (t1_id, t1_val) VALUES ( 3 ,  30 );
INSERT INTO table1 (t1_id, t1_val) VALUES ( 4 ,  40 );

INSERT INTO table2 (t2_id, t2_t1_id, t2_val) VALUES ( 1 ,  1 ,  100 );
INSERT INTO table2 (t2_id, t2_t1_id, t2_val) VALUES ( 2 ,  1 ,  200 );
INSERT INTO table2 (t2_id, t2_t1_id, t2_val) VALUES ( 3 ,  1 ,  300 );
INSERT INTO table2 (t2_id, t2_t1_id, t2_val) VALUES ( 4 ,  2 ,  400 );
INSERT INTO table2 (t2_id, t2_t1_id, t2_val) VALUES ( 5 ,  2 ,  500 );
INSERT INTO table2 (t2_id, t2_t1_id, t2_val) VALUES ( 6 ,  2 ,  600 );
INSERT INTO table2 (t2_id, t2_t1_id, t2_val) VALUES ( 7 ,  4 ,  700 );

SELECT pg_catalog.setval(pg_catalog.pg_get_serial_sequence('table1', 't1_id'),  4 , true);
SELECT pg_catalog.setval(pg_catalog.pg_get_serial_sequence('table2', 't2_id'),  7 , true);

ALTER TABLE ONLY table2
    ADD CONSTRAINT "FK_t2_t1" FOREIGN KEY (t2_t1_id) REFERENCES table1(t1_id);

select t2_id, t2_val from
       table2 inner join table1
              on t2_t1_id = t1_id
where t1_id =  2 ;

--План отличный все в порядке

Nested Loop  (cost= 0 . 00 .. 2 . 18  rows= 4  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 3  loops= 1 )
  ->  Seq Scan on table1  (cost= 0 . 00 .. 1 . 05  rows= 1  width= 4 ) (actual time= 0 . 000 .. 0 . 000  rows= 1  loops= 1 )
        Filter: (t1_id =  2 )
  ->  Seq Scan on table2  (cost= 0 . 00 .. 1 . 09  rows= 4  width= 12 ) (actual time= 0 . 000 .. 0 . 000  rows= 3  loops= 1 )
        Filter: ( 2  = t2_t1_id)

select t2_id, t2_val from
       table2 inner join table1
              on t1_id = t2_t1_id
where t1_id >  1 ;

--А вот тут собственно вопрос. Куда подевался Nested Loop. Как получается, что фильтрация по t1_id в самом конце???
Hash Join  (cost= 1 . 06 .. 2 . 24  rows= 7  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 4  loops= 1 )
  Hash Cond: ("outer".t2_t1_id = "inner".t1_id)
  ->  Seq Scan on table2  (cost= 0 . 00 .. 1 . 07  rows= 7  width= 12 ) (actual time= 0 . 000 .. 0 . 000  rows= 7  loops= 1 )
  ->  Hash  (cost= 1 . 05 .. 1 . 05  rows= 4  width= 4 ) (actual time= 0 . 000 .. 0 . 000  rows= 0  loops= 1 )
        ->  Seq Scan on table1  (cost= 0 . 00 .. 1 . 05  rows= 4  width= 4 ) (actual time= 0 . 000 .. 0 . 000  rows= 3  loops= 1 )
              Filter: (t1_id >  1 )
...
Рейтинг: 0 / 0
08.09.2005, 09:49
    #33257829
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Код: plaintext
1.
2.
3.
4.
5.
6.
Hash Join  (cost= 1 . 06 .. 2 . 24  rows= 7  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 4  loops= 1 )
  Hash Cond: ("outer".t2_t1_id = "inner".t1_id)
  ->  Seq Scan on table2  (cost= 0 . 00 .. 1 . 07  rows= 7  width= 12 ) (actual time= 0 . 000 .. 0 . 000  rows= 7  loops= 1 )
  ->  Hash  (cost= 1 . 05 .. 1 . 05  rows= 4  width= 4 ) (actual time= 0 . 000 .. 0 . 000  rows= 0  loops= 1 )
        ->  Seq Scan on table1  (cost= 0 . 00 .. 1 . 05  rows= 4  width= 4 ) (actual time= 0 . 000 .. 0 . 000  rows= 3  loops= 1 )
              Filter: (t1_id >  1 )
Paul ChabinskyА вот тут собственно вопрос. Куда подевался Nested Loop.Оптимизатор выбрал другой план, так как возможно несколько разных вариантов, и он выбрал из них наиболее дешевый по его мнению. Попробуйте "set enable_hash_join to off; explain analyze ...".

Paul ChabinskyКак получается, что фильтрация по t1_id в самом конце???Запрос, если смотреть на текстовую выдачу EXPLAIN, выполняется не сверху внизх, а из глубины наружу, то есть справа налево. (Не думаю, что понятно объяснил.:) Здесь постгрес последовательно прочитал таблицу 2 и закачал ее в хэш, потом последовательно читал строки из таблицы 1, фильтровал их по условию t1_id>1, соединял со строками из хэша по условию t2_t1_id=t1_id, и отдавал наружу.

http://www.postgresql.org/docs/8.0/static/performance-tips.html#USING-EXPLAIN
...
Рейтинг: 0 / 0
08.09.2005, 11:58
    #33258260
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Так вот меня и интересует, почему он сначала всю таблицу table2 в кэш берет, и только потом фильтрует первую и джойнит, когда надо сначало отфильтровать первую таблицу, получить значения форейнки и только потом выбирать записи из второй таблицы, и с ними джойниться.
...
Рейтинг: 0 / 0
08.09.2005, 12:12
    #33258325
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Код: plaintext
1.
2.
set enable_hashjoin to off;
explain analyze select * from table1 t1, table2 t2
where t1.t1_id >  1  and t1.t1_id = t2.t2_t1_id

Просто шедевр выдает :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Merge Join  (cost= 2 . 26 .. 2 . 38  rows= 7  width= 20 ) (actual time= 0 . 000 .. 0 . 000  rows= 4  loops= 1 )
  Merge Cond: ("outer".t1_id = "inner".t2_t1_id)
  ->  Sort  (cost= 1 . 09 .. 1 . 10  rows= 4  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 3  loops= 1 )
        Sort Key: t1.t1_id
        ->  Seq Scan on table1 t1  (cost= 0 . 00 .. 1 . 05  rows= 4  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 3  loops= 1 )
              Filter: (t1_id >  1 )
  ->  Sort  (cost= 1 . 17 .. 1 . 19  rows= 7  width= 12 ) (actual time= 0 . 000 .. 0 . 000  rows= 7  loops= 1 )
        Sort Key: t2.t2_t1_id
        ->  Seq Scan on table2 t2  (cost= 0 . 00 .. 1 . 07  rows= 7  width= 12 ) (actual time= 0 . 000 .. 0 . 000  rows= 7  loops= 1 )

Насколько я понимаю он просто перестал брать таблицы в кэш, чем мне все это грозит, да тем что когда оптимизатор поймет, что не сможет закачать данные в оперативку он будет делать мердж джоины вместо хэш джоинов...
...
Рейтинг: 0 / 0
08.09.2005, 13:15
    #33258579
Sad Spirit
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
В данном конкретном случае абсолютно пох. какие планы выбирает оптимизатор. Планы надо смотреть на реальных объёмах данных.

Теперь к вопросу. Учтём, что PostgreSQL читает данные блоками по 8 кб. Таким образом, каждая из вышеописанных таблиц умещается в 1 блоке, и сделать seq scan (который прочитает 1 блок) быстрее, чем index scan (который прочитает 2 блока --- heap и индекс). Поэтому выбираются планы, подразумевающие полный просмотр. Теперь, если у нас есть целиком таблица, то быстрее будет не Nested Loop (т.е. линейный просмотр на каждой итерации), а нечто другое (соединение по хэшу или слияние двух отсортированных результатов), что и выбирается.

Все пространные рассуждения касательно "кэша" и "оперативки" отнесём на счёт незнания архитектуры данной СУБД. ;)
...
Рейтинг: 0 / 0
08.09.2005, 14:27
    #33258865
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Да я действительно не знаю тонкостей PG. :)
По этому и задаю вопросы :)
Сначало я именно так и подумал, что ему выгодней делать хэшджоин чем нестедлуп на таком объеме данных, но сомнения возникли именно потому, что при явном указании t1_id = 2, делается нестед луп...
...
Рейтинг: 0 / 0
08.09.2005, 14:57
    #33258965
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Paul ChabinskyТак вот меня и интересует, почему он сначала всю таблицу table2 в кэш беретВидимо не догоняет, что из условий t1_id=t2_t1_id и t1_id>1 следует, что t2_t1_id>1. Попробуйте ему в этом помочь: ... where t1_id > 1 and t2_t1_id>1.

Paul Chabinskyкогда надо сначало отфильтровать первую таблицу, получить значения форейнки и только потом выбирать записи из второй таблицы, и с ними джойниться."Надо" или "можно"? :) Процитирую себя: "так как возможно несколько разных вариантов, и он выбрал из них наиболее дешевый по его мнению".

Paul Chabinskyкогда оптимизатор поймет, что не сможет закачать данные в оперативку он будет делать мердж джоины вместо хэш джоиновНе факт. Проверить правильность этого утверждения можно копая сорцы, mailing-lists,..

Paul ChabinskyСначало я именно так и подумал, что ему выгодней делать хэшджоин чем нестедлуп на таком объеме данныхСтоит ли вообще заглядывать в планы на таком объеме данных? Практичнее играться с реальными объемами.
...
Рейтинг: 0 / 0
08.09.2005, 15:13
    #33259024
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Код: plaintext
1.
...
Рейтинг: 0 / 0
08.09.2005, 15:21
    #33259068
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Код: 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.
select count(*) from table1;

 1048576 

select count(*) from table2;

 524294 

CREATE INDEX table2_idx
  ON test.table2
  USING btree
  (t2_t1_id);

select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2 

 1 ; 10 ; 1 ; 1 ; 100 
 1 ; 10 ; 2 ; 1 ; 200 
 1 ; 10 ; 3 ; 1 ; 300 
 1 ; 10 ; 524292 ; 1 ; 100 
 1 ; 10 ; 524293 ; 1 ; 200 
 1 ; 10 ; 524294 ; 1 ; 300 


Hash Join  (cost= 4 . 68 .. 11209 . 62  rows= 53  width= 20 ) (actual time= 0 . 000 .. 2538 . 000  rows= 6  loops= 1 )
  Hash Cond: ("outer".t2_t1_id = "inner".t1_id)
  ->  Seq Scan on table2 t2  (cost= 0 . 00 .. 8582 . 94  rows= 524294  width= 12 ) (actual time= 0 . 000 .. 1502 . 000  rows= 524294  loops= 1 )
  ->  Hash  (cost= 4 . 42 .. 4 . 42  rows= 105  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 0  loops= 1 )
        ->  Index Scan using table1_pkey on table1 t1  (cost= 0 . 00 .. 4 . 42  rows= 105  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 1  loops= 1 )
              Index Cond: (t1_id <  2 )
Total runtime:  2538 . 000  ms


...
Рейтинг: 0 / 0
08.09.2005, 15:30
    #33259090
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Теперь почему я вообще эту тему поднял
Вы только очень сильно матом на меня не кричите, я честно ищу помощи, или приговора :(

Я обсолютно такую же структуру сделал в MSSQL 2k

Код: 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.
select count(*) from table1;

 1572864 

select count(*) from table2;

 786444 

select * from table1 t1
	inner join table2 t2 on t1_id = t2_t1_id
where t1_id <  2 

 1 	 10 	 1 	 1 	 100 
 1 	 10 	 2 	 1 	 200 
 1 	 10 	 3 	 1 	 300 
 1 	 10 	 4 	 1 	 400 
 1 	 10 	 5 	 1 	 500 
 1 	 10 	 6 	 1 	 600 
 1 	 10 	 786439 	 1 	 100 
 1 	 10 	 786440 	 1 	 200 
 1 	 10 	 786441 	 1 	 300 
 1 	 10 	 786442 	 1 	 400 
 1 	 10 	 786443 	 1 	 500 
 1 	 10 	 786444 	 1 	 600 

Rows        Executes    StmtText                                                                                                                          StmtId      NodeId      Parent      PhysicalOp                     LogicalOp                      
----------- ----------- --------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ 
 12            1            select * from table1 t1 inner join table2 t2 on t1_id = t2_t1_id where t1_id <  2                                                    11            1             0            NULL                           NULL                           
 12            1              |--Bookmark Lookup(BOOKMARK:([Bmk1001]), OBJECT:([zx].[dbo].[Table2] AS [t2]))                                                  11          3           1           Bookmark Lookup                Bookmark Lookup                
 12            1                   |--Nested Loops(Inner Join, OUTER REFERENCES:([t1].[t1_id]) WITH PREFETCH)                                                 11          4           3           Nested Loops                   Inner Join                     
 1             1                        |--Clustered Index Seek(OBJECT:([zx].[dbo].[Table1].[PK_Table1] AS [t1]), SEEK:([t1].[t1_id] < 2) ORDERED FORWARD)    11          6           4           Clustered Index Seek           Clustered Index Seek           
 12            1                        |--Index Seek(OBJECT:([zx].[dbo].[Table2].[IX_Table2] AS [t2]), SEEK:([t2].[t2_t1_id]=[t1].[t1_id]) ORDERED FORWARD)  11          7           4           Index Seek                     Index Seek                     

Duration: 13ms
...
Рейтинг: 0 / 0
08.09.2005, 15:32
    #33259099
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Возможно ли увеличить производительность Постгреса...
Ведь это элементарный запрос, если запрос будет сложнее я хочу знать что меня ждет...
...
Рейтинг: 0 / 0
08.09.2005, 16:59
    #33259440
XM
XM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Paul Chabinsky wrote:
> Возможно ли увеличить производительность Постгреса...

Можно, исходники оптимизатора открыты (эт вам не MSSQL) :)

> Ведь это элементарный запрос, если запрос будет сложнее я хочу знать что
> меня ждет...

ХЗ что тебя может ждать - решения оптимизатора по планам запросов
зависят от объемов реальных данных, наличия и типов индексов, но, опять
же, сорцы открыты - бери анализируй :) (слаб о ?) , а данные можно
нагененирить, натестить. Но, ИМХО, реальные траблы вылезут только на
реальных, активно используемых данных.
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
08.09.2005, 17:12
    #33259481
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Paul Chabinsky
Код: plaintext
1.
2.
3.
4.
5.
6.
Hash Join  (cost= 4 . 68 .. 11209 . 62  rows= 53  width= 20 ) (actual time= 0 . 000 .. 2538 . 000  rows= 6  loops= 1 )
  Hash Cond: ("outer".t2_t1_id = "inner".t1_id)
  ->  Seq Scan on table2 t2  (cost= 0 . 00 .. 8582 . 94  rows= 524294  width= 12 ) (actual time= 0 . 000 .. 1502 . 000  rows= 524294  loops= 1 )
  ->  Hash  (cost= 4 . 42 .. 4 . 42  rows= 105  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 0  loops= 1 )
        ->  Index Scan using table1_pkey on table1 t1  (cost= 0 . 00 .. 4 . 42  rows= 105  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 1  loops= 1 )
              Index Cond: (t1_id <  2 )
Total runtime:  2538 . 000  ms
"Видимо не догоняет, что из условий t1_id=t2_t1_id и t1_id>1 следует, что t2_t1_id>1. Попробуйте ему в этом помочь: ... where t1_id > 1 and t2_t1_id>1."

Покажите пожалуйста, что получается с set enable_hashjoin to off;

Paul ChabinskyТеперь почему я вообще эту тему поднял... Я обсолютно такую же структуру сделал в MSSQL 2kLucky MSSQL, возможно, на этом запросе. Когда мы сидели на оракле, тоже приходилось тюнить запросы. :(

Paul ChabinskyВозможно ли увеличить производительность Постгреса...Нажмите одновременно Q-W-T-Y. Появится 100 жизни, оружия, сервер станет быстрее и умнее.
...
Рейтинг: 0 / 0
08.09.2005, 17:26
    #33259537
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Ребят, я написал про MS только для того чтоб понятней стал мой вопрос.

2 LeXa NalBat
Большое спасибо, действительно постгресу надо было помочь.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
-- set enable_hashjoin to on/off роли не играет, план в обоих случаях одинаковый
explain analyze select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  and t2_t1_id <  2 ;

"Merge Join  (cost=0.00..4.49 rows=1 width=20) (actual time=0.000..0.000 rows=6 loops=1)"
"  Merge Cond: ("outer".t1_id = "inner".t2_t1_id)"
"  ->  Index Scan using table1_pkey on table1 t1  (cost=0.00..4.42 rows=105 width=8) (actual time=0.000..0.000 rows=1 loops=1)"
"        Index Cond: (t1_id < 2)"
"  ->  Index Scan using table2_idx on table2 t2  (cost=0.00..4.43 rows=1 width=12) (actual time=0.000..0.000 rows=6 loops=1)"
"        Index Cond: (t2_t1_id < 2)"
"Total runtime: 0.000 ms"


...
Рейтинг: 0 / 0
08.09.2005, 17:37
    #33259578
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
2 LeXa NalBat

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
set enable_hashjoin to off;
explain analyze select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  /* and t2_t1_id < 2 */;

"Merge Join  (cost=86120.91..88742.96 rows=53 width=20) (actual time=8276.000..8276.000 rows=6 loops=1)"
"  Merge Cond: ("outer".t1_id = "inner".t2_t1_id)"
"  ->  Index Scan using table1_pkey on table1 t1  (cost=0.00..4.42 rows=105 width=8) (actual time=0.000..0.000 rows=1 loops=1)"
"        Index Cond: (t1_id < 2)"
"  ->  Sort  (cost=86120.91..87431.65 rows=524294 width=12) (actual time=8276.000..8276.000 rows=7 loops=1)"
"        Sort Key: t2.t2_t1_id"
"        ->  Seq Scan on table2 t2  (cost=0.00..8582.94 rows=524294 width=12) (actual time=0.000..1699.000 rows=524294 loops=1)"
"Total runtime: 8354.000 ms"
...
Рейтинг: 0 / 0
08.09.2005, 17:53
    #33259622
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Paul Chabinsky
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
set enable_hashjoin to off;
explain analyze select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  /* and t2_t1_id < 2 */;

"Merge Join  (cost=86120.91..88742.96 rows=53 width=20) (actual time=8276.000..8276.000 rows=6 loops=1)"
"  Merge Cond: ("outer".t1_id = "inner".t2_t1_id)"
"  ->  Index Scan using table1_pkey on table1 t1  (cost=0.00..4.42 rows=105 width=8) (actual time=0.000..0.000 rows=1 loops=1)"
"        Index Cond: (t1_id < 2)"
"  ->  Sort  (cost=86120.91..87431.65 rows=524294 width=12) (actual time=8276.000..8276.000 rows=7 loops=1)"
"        Sort Key: t2.t2_t1_id"
"        ->  Seq Scan on table2 t2  (cost=0.00..8582.94 rows=524294 width=12) (actual time=0.000..1699.000 rows=524294 loops=1)"
"Total runtime: 8354.000 ms"
Теперь пожалуйста еще дополнительно set enable_mergejoin to off;
...
Рейтинг: 0 / 0
08.09.2005, 18:05
    #33259656
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
2 LeXa NalBat
Я к сожалению уже убил данные тестовые, ждать вставку сново и ваакум не хочется.
Но я на 99% процентов уверен что самый быстрый вариант будет с мердж джоином.
Моей ошибкой было то, что я недостаточно понятно объяснил оптимизатору постгреса условие выборки... дальше он сам сделал все красиво...
Хотя конечно то, что приходица подобные вещи дописывать несколько удивляет и заставляет крепко задуматься.
...
Рейтинг: 0 / 0
08.09.2005, 23:08
    #33259975
Sad Spirit
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Paul Chabinsky
Сначало я именно так и подумал, что ему выгодней делать хэшджоин чем нестедлуп на таком объеме данных, но сомнения возникли именно потому, что при явном указании t1_id = 2, делается нестед луп...
Дык посмотри: он в одном результате оценивает количество полученных строк единицей. Какой смысл единственную строку сортировать / кэшировать?
...
Рейтинг: 0 / 0
08.09.2005, 23:14
    #33259978
Sad Spirit
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Paul Chabinsky
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2 


Hash Join  (cost= 4 . 68 .. 11209 . 62  rows= 53  width= 20 ) (actual time= 0 . 000 .. 2538 . 000  rows= 6  loops= 1 )
  Hash Cond: ("outer".t2_t1_id = "inner".t1_id)
  ->  Seq Scan on table2 t2  (cost= 0 . 00 .. 8582 . 94  rows= 524294  width= 12 ) (actual time= 0 . 000 .. 1502 . 000  rows= 524294  loops= 1 )
  ->  Hash  (cost= 4 . 42 .. 4 . 42  rows= 105  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 0  loops= 1 )
        ->  Index Scan using table1_pkey on table1 t1  (cost= 0 . 00 .. 4 . 42  rows= 105  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 1  loops= 1 )
              Index Cond: (t1_id <  2 )
Total runtime:  2538 . 000  ms


Здесь несколько смущает, что на два порядка разница между ожидаемым и полученным числом записей:
Код: plaintext
1.
Index Scan using table1_pkey on table1 t1  (cost= 0 . 00 .. 4 . 42  rows= 105  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 1  loops= 1 )
Может попробовать поиграться со STATISTIC TARGET или как его там для этой таблицы?
...
Рейтинг: 0 / 0
09.09.2005, 09:59
    #33260353
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Paul ChabinskyЯ к сожалению уже убил данные тестовые, ждать вставку сново и ваакум не хочется.Жаль. :( Хотелось бы понять, что постгрес думает про нестедлуп, из-за чего его цена получилась дороже?

Paul ChabinskyХотя конечно то, что приходица подобные вещи дописывать несколько удивляет и заставляет крепко задуматься.Может быть это не такая уж и тривиальная вещь, по крайней мере для разных типов id1 и id2. Хотя в вашем примере типы одинаковые.

Ведь заметьте, MSSQL выбрал один из планов, которые возможны и в постгресе. Нестедлуп с outer по t1 (id1<2) и inner по t2 (id2=id1), а не наоборот - outer по t2 (id2<2) и inner по t1 (id1=id2).

P.S.: Несколько раз писал письма разработчикам, почему бы не сделать вот такую простую и правильную вещь? А после их ответа становилось понятно, что это просто и правильно только в моем случае, но не в общем. :(
...
Рейтинг: 0 / 0
09.09.2005, 13:31
    #33261203
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
set enable_hashjoin to false;
set enable_mergejoin to false;

select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  /*and t2_t1_id < 2*/;

Nested Loop  (cost= 0 . 00 .. 6390815 . 48  rows= 211  width= 20 ) (actual time= 0 . 000 .. 20640 . 000  rows= 6  loops= 1 )
  ->  Seq Scan on table2 t2  (cost= 0 . 00 .. 34329 . 58  rows= 2097158  width= 12 ) (actual time= 0 . 000 .. 5672 . 000  rows= 2097158  loops= 1 )
  ->  Index Scan using table1_pkey on table1 t1  (cost= 0 . 00 .. 3 . 02  rows= 1  width= 8 ) (actual time= 0 . 003 .. 0 . 003  rows= 0  loops= 2097158 )
        Index Cond: ((t1.t1_id <  2 ) AND (t1.t1_id = "outer".t2_t1_id))
Total runtime:  20640 . 000  ms


Hash Join  (cost= 5 . 53 .. 44823 . 01  rows= 211  width= 20 ) (actual time= 0 . 000 .. 10109 . 000  rows= 6  loops= 1 )
  Hash Cond: ("outer".t2_t1_id = "inner".t1_id)
  ->  Seq Scan on table2 t2  (cost= 0 . 00 .. 34329 . 58  rows= 2097158  width= 12 ) (actual time= 0 . 000 .. 5596 . 000  rows= 2097158  loops= 1 )
  ->  Hash  (cost= 5 . 13 .. 5 . 13  rows= 158  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 0  loops= 1 )
        ->  Index Scan using table1_pkey on table1 t1  (cost= 0 . 00 .. 5 . 13  rows= 158  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 1  loops= 1 )
              Index Cond: (t1_id <  2 )
Total runtime:  10109 . 000  ms


...
Рейтинг: 0 / 0
09.09.2005, 13:34
    #33261211
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Блин случайно запостилось, в общим второй селект делался:
Код: 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.
set enable_hashjoin to true;
set enable_mergejoin to true;
select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  /*and t2_t1_id < 2*/;

set enable_hashjoin to false;
set enable_mergejoin to false;
select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  and t2_t1_id <  2 ;

Nested Loop  (cost= 0 . 00 .. 7 . 39  rows= 1  width= 20 ) (actual time= 0 . 000 .. 0 . 000  rows= 6  loops= 1 )
  ->  Index Scan using table2_idx on table2 t2  (cost= 0 . 00 .. 4 . 36  rows= 1  width= 12 ) (actual time= 0 . 000 .. 0 . 000  rows= 6  loops= 1 )
        Index Cond: (t2_t1_id <  2 )
  ->  Index Scan using table1_pkey on table1 t1  (cost= 0 . 00 .. 3 . 02  rows= 1  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 1  loops= 6 )
        Index Cond: ((t1.t1_id <  2 ) AND (t1.t1_id = "outer".t2_t1_id))
Total runtime:  0 . 000  ms

set enable_hashjoin to true;
set enable_mergejoin to true;
select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  and t2_t1_id <  2 ;

Merge Join  (cost= 0 . 00 .. 4 . 41  rows= 1  width= 20 ) (actual time= 0 . 000 .. 0 . 000  rows= 6  loops= 1 )
  Merge Cond: ("outer".t1_id = "inner".t2_t1_id)
  ->  Index Scan using table1_pkey on table1 t1  (cost= 0 . 00 .. 5 . 13  rows= 158  width= 8 ) (actual time= 0 . 000 .. 0 . 000  rows= 1  loops= 1 )
        Index Cond: (t1_id <  2 )
  ->  Index Scan using table2_idx on table2 t2  (cost= 0 . 00 .. 4 . 36  rows= 1  width= 12 ) (actual time= 0 . 000 .. 0 . 000  rows= 6  loops= 1 )
        Index Cond: (t2_t1_id <  2 )
Total runtime:  0 . 000  ms


...
Рейтинг: 0 / 0
09.09.2005, 14:03
    #33261320
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Paul Chabinsky
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
set enable_hashjoin to false;
set enable_mergejoin to false;

select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  /*and t2_t1_id < 2*/;

Nested Loop  (cost= 0 . 00 .. 6390815 . 48  rows= 211  width= 20 ) (actual time= 0 . 000 .. 20640 . 000  rows= 6  loops= 1 )
  ->  Seq Scan on table2 t2  (cost= 0 . 00 .. 34329 . 58  rows= 2097158  width= 12 ) (actual time= 0 . 000 .. 5672 . 000  rows= 2097158  loops= 1 )
  ->  Index Scan using table1_pkey on table1 t1  (cost= 0 . 00 .. 3 . 02  rows= 1  width= 8 ) (actual time= 0 . 003 .. 0 . 003  rows= 0  loops= 2097158 )
        Index Cond: ((t1.t1_id <  2 ) AND (t1.t1_id = "outer".t2_t1_id))
Total runtime:  20640 . 000  ms
Сделайте пожалуйста еще дополнительно set enable_seqscan to off.
...
Рейтинг: 0 / 0
09.09.2005, 15:32
    #33261615
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
set enable_hashjoin to false;
set enable_mergejoin to false;
set enable_seqscan to false;
explain analyze select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  /*and t2_t1_id < 2*/;



"Nested Loop  (cost=0.00..10949098.75 rows=211 width=20) (actual time=63.000..22219.000 rows=6 loops=1)"
"  ->  Index Scan using table2_idx on table2 t2  (cost=0.00..4592612.85 rows=2097158 width=12) (actual time=16.000..7540.000 rows=2097158 loops=1)"
"  ->  Index Scan using table1_pkey on table1 t1  (cost=0.00..3.02 rows=1 width=8) (actual time=0.002..0.002 rows=0 loops=2097158)"
"        Index Cond: ((t1.t1_id < 2) AND (t1.t1_id = "outer".t2_t1_id))"
"Total runtime: 22219.000 ms"
...
Рейтинг: 0 / 0
09.09.2005, 16:01
    #33261713
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Где мой Nested Loop %)
Paul Chabinsky
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
set enable_hashjoin to false;
set enable_mergejoin to false;
set enable_seqscan to false;
explain analyze select * from test.table1 t1 inner join test.table2 t2
	on t1_id = t2_t1_id
where t1_id <  2  /*and t2_t1_id < 2*/;



"Nested Loop  (cost=0.00..10949098.75 rows=211 width=20) (actual time=63.000..22219.000 rows=6 loops=1)"
"  ->  Index Scan using table2_idx on table2 t2  (cost=0.00..4592612.85 rows=2097158 width=12) (actual time=16.000..7540.000 rows=2097158 loops=1)"
"  ->  Index Scan using table1_pkey on table1 t1  (cost=0.00..3.02 rows=1 width=8) (actual time=0.002..0.002 rows=0 loops=2097158)"
"        Index Cond: ((t1.t1_id < 2) AND (t1.t1_id = "outer".t2_t1_id))"
"Total runtime: 22219.000 ms"
Еще такой тест:
prepare fff(int) as select * from test.table2 t2 where t2_t1_id = $1;
explain analyze execute fff(1);
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Где мой Nested Loop %) / 25 сообщений из 25, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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