powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Проходит полный Seq Scan вместо индекса.
13 сообщений из 13, страница 1 из 1
Проходит полный Seq Scan вместо индекса.
    #39370300
nateless
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Приветствую,

Не пойму почему используется Seq Scan вместо индекса, обходит 500М записей ради ~1300.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
 Nested Loop  (cost=3223965.89..20135328.45 rows=2539646 width=115) (actual time=94589.422..131043.163 rows=1381 loops=1)
   Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, t2.trx_id, o1.addresses, o1.amount
   ->  Hash Join  (cost=3223965.32..17251459.53 rows=2539646 width=54) (actual time=94589.376..131032.096 rows=1381 loops=1)
         Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, o1.addresses, o1.amount, o1.transaction_id
         Hash Cond: (o1.id = i0.output_id)
         ->  Seq Scan on public.outputs o1  (cost=0.00..10832460.94 rows=507146494 width=41) (actual time=0.014..48529.711 rows=505393641 loops=1)
               Output: o1.id, o1.transaction_id, o1.addresses, o1."position", o1.amount, o1.type, o1.req_sigs, o1.spent
         ->  Hash  (cost=3192219.74..3192219.74 rows=2539646 width=21) (actual time=10.803..10.803 rows=1381 loops=1)
               Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, i0.output_id
               Buckets: 4194304  Batches: 1  Memory Usage: 32844kB
               ->  Index Scan using inputs_transaction_id_position_index on public.inputs i0  (cost=0.57..3192219.74 rows=2539646 width=21) (actual time=0.037..10.093 rows=2731 loops=1)
                     Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, i0.output_id
                     Index Cond: (i0.transaction_id = ANY ('{165237854,.......}'::integer[]))
   ->  Index Scan using transactions_pkey on public.transactions t2  (cost=0.57..1.13 rows=1 width=69) (actual time=0.007..0.007 rows=1 loops=1381)
         Output: t2.id, t2.block_id, t2.trx_id, t2.version, t2.index, t2.lock_time, t2.size, t2."time", t2.inputs_count, t2.outputs_count, t2.mem_pool, t2.total_in_value, t2.total_out_value, t2.est_out_value, t2.fee, t2.created_at
         Index Cond: (t2.id = o1.transaction_id)
 Planning time: 7.658 ms
 Execution time: 131045.677 ms
(18 rows)



Запрос
Код: plsql
1.
2.
3.
4.
5.
6.
explain (analyze, verbose) 
SELECT i0."id", i0."transaction_id", i0."position", i0."is_coinbase", i0."vout", t2."trx_id", o1."addresses", o1."amount" 
FROM "inputs" AS i0 
INNER JOIN "outputs" AS o1 ON o1."id" = i0."output_id" 
INNER JOIN "transactions" AS t2 ON t2."id" = o1."transaction_id" 
WHERE (i0."transaction_id" = ANY(ARRAY[165237854,.......]));



Естественно есть primary индекс на outputs.id:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
                                                  Table "public.outputs"
     Column     |   Type    |                      Modifiers                       | Storage  | Stats target | Description
----------------+-----------+------------------------------------------------------+----------+--------------+-------------
 id             | integer   | not null default nextval('outputs_id_seq'::regclass) | plain    |              |
 transaction_id | integer   |                                                      | plain    |              |
 addresses      | integer[] | default ARRAY[]::integer[]                           | extended |              |
 position       | integer   |                                                      | plain    |              |
 amount         | bigint    |                                                      | plain    |              |
 type           | integer   |                                                      | plain    |              |
 req_sigs       | integer   |                                                      | plain    |              |
 spent          | boolean   | default false                                        | plain    |              |
Indexes:
    "outputs_pkey" PRIMARY KEY, btree (id)
    "outputs_addresses_index" btree (addresses)
    "outputs_transaction_id_position_index" btree (transaction_id, "position")
Foreign-key constraints:
    "outputs_transaction_id_fkey" FOREIGN KEY (transaction_id) REFERENCES transactions(id)
Referenced by:
    TABLE "inputs" CONSTRAINT "inputs_output_id_fkey" FOREIGN KEY (output_id) REFERENCES outputs(id)
    TABLE "output_datas" CONSTRAINT "output_datas_output_id_fkey" FOREIGN KEY (output_id) REFERENCES outputs(id)
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370323
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nateless,

потому что база считает что там не 1300 записей будет а
Код: plaintext
1.
2.
3.
               ->  Index Scan using inputs_transaction_id_position_index on public.inputs i0  (cost=0.57..3192219.74 rows=2539646 width=21) (actual time=0.037..10.093 rows=2731 loops=1)
                     Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, i0.output_id
                     Index Cond: (i0.transaction_id = ANY ('{165237854,.......}'::integer[]))

2539646 записей.... и тут уже появляются варианты в таком случае как будет эффективнее.

Вот не надо делать =ANY(ARRAY[]) никогда вместо IN так как он не будет нормально количество строк в ответе оценивать.

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370389
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

вообще то это проблема планировщика. и колхозников, его писавшего.


2ТС пж -- изначально поделие студентов. толпы математиксов над ним не чахли. поэтому не стоит удивляться его поведению. но изучать. и пользоваться "как есть".
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370393
nateless
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk,

Попробовали с IN, почему-то в explain выдает все тот же ANYб может быть что он сам преобразует в этот формат?

Код: plsql
1.
explain (analyze, verbose) SELECT i0."id", i0."transaction_id", i0."position", i0."is_coinbase", i0."vout", t2."trx_id", o1."addresses", o1."amount" FROM "inputs" AS i0 INNER JOIN "outputs" AS o1 ON o1."id" = i0."output_id" INNER JOIN "transactions" AS t2 ON t2."id" = o1."transaction_id" WHERE (i0."transaction_id" IN (165237854, ...));



Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Nested Loop  (cost=3223965.89..20059273.37 rows=2539646 width=115) (actual time=87762.858..121260.976 rows=1381 loops=1)
   Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, t2.trx_id, o1.addresses, o1.amount
   ->  Hash Join  (cost=3223965.32..17203052.04 rows=2539646 width=54) (actual time=87762.818..121250.902 rows=1381 loops=1)
         Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, o1.addresses, o1.amount, o1.transaction_id
         Hash Cond: (o1.id = i0.output_id)
         ->  Seq Scan on public.outputs o1  (cost=0.00..10795008.64 rows=505393664 width=41) (actual time=0.010..48977.366 rows=505393641 loops=1)
               Output: o1.id, o1.transaction_id, o1.addresses, o1."position", o1.amount, o1.type, o1.req_sigs, o1.spent
         ->  Hash  (cost=3192219.74..3192219.74 rows=2539646 width=21) (actual time=10.663..10.663 rows=1381 loops=1)
               Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, i0.output_id
               Buckets: 4194304  Batches: 1  Memory Usage: 32844kB
               ->  Index Scan using inputs_transaction_id_position_index on public.inputs i0  (cost=0.57..3192219.74 rows=2539646 width=21) (actual time=0.036..10.032 rows=2731 loops=1)
                     Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, i0.output_id
                     Index Cond: (i0.transaction_id = ANY ('{165237854,....}'::integer[]))
   ->  Index Scan using transactions_pkey on public.transactions t2  (cost=0.57..1.11 rows=1 width=69) (actual time=0.006..0.006 rows=1 loops=1381)
         Output: t2.id, t2.block_id, t2.trx_id, t2.version, t2.index, t2.lock_time, t2.size, t2."time", t2.inputs_count, t2.outputs_count, t2.mem_pool, t2.total_in_value, t2.total_out_value, t2.est_out_value, t2.fee, t2.created_at
         Index Cond: (t2.id = o1.transaction_id)
 Planning time: 9.444 ms
 Execution time: 121262.030 ms
(18 rows)
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370400
nateless
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

Ну с MySQL мы тоже наплевались в свое время, особенно после крашей. У постгры есть свои минусы, но данный хочется все-таки обойти :)
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370403
nateless
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, нашел вот на оф мейллисте postgresql:

8.2 will treat them equivalently (in fact, it converts IN (...) to
= ANY (ARRAY[...]) !). So depending on your time horizon, you might
wish to stick with whichever is cleaner for your calling code.
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370407
nateless
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
При замене ANY на ALL получается сократить время чуть более чем в два раза

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
 Nested Loop  (cost=1.14..807648483.90 rows=1 width=115) (actual time=56823.426..56823.426 rows=0 loops=1)
   Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, t2.trx_id, o1.addresses, o1.amount
   ->  Nested Loop  (cost=0.57..807648482.78 rows=1 width=54) (actual time=56823.425..56823.425 rows=0 loops=1)
         Output: i0.id, i0.transaction_id, i0."position", i0.is_coinbase, i0.vout, o1.addresses, o1.amount, o1.transaction_id
         ->  Seq Scan on public.inputs i0  (cost=0.00..807648474.18 rows=1 width=21) (actual time=56823.421..56823.421 rows=0 loops=1)
               Output: i0.id, i0.transaction_id, i0.output_id, i0.is_coinbase, i0."position", i0.vout
               Filter: (i0.transaction_id = ALL ('{165237854,...}'::integer[]))
               Rows Removed by Filter: 461107714
         ->  Index Scan using outputs_pkey on public.outputs o1  (cost=0.57..8.59 rows=1 width=41) (never executed)
               Output: o1.id, o1.transaction_id, o1.addresses, o1."position", o1.amount, o1.type, o1.req_sigs, o1.spent
               Index Cond: (o1.id = i0.output_id)
   ->  Index Scan using transactions_pkey on public.transactions t2  (cost=0.57..1.11 rows=1 width=69) (never executed)
         Output: t2.id, t2.block_id, t2.trx_id, t2.version, t2.index, t2.lock_time, t2.size, t2."time", t2.inputs_count, t2.outputs_count, t2.mem_pool, t2.total_in_value, t2.total_out_value, t2.est_out_value, t2.fee, t2.created_at
         Index Cond: (t2.id = o1.transaction_id)
 Planning time: 7.044 ms
 Execution time: 56823.531 ms
(16 rows)
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370438
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nateless8.2 will treat them
а у вас какой ?

если больше 9.3 и вы знаете , что возврат из под ANY заведомо невелик -- попробуйте запинать лейтералами (вместо иннер джойнов) с хеш--джойна на нестед луп по результатам ина (ANY) по i0.
если же простынка эни возвратит на деле лямы -- вы проиграете хеш--джойну очень и очень много

и да , проанализировать i0 наверное невредно.
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370446
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
т.е. пофантазируйте на тему
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
explain --(analyze, verbose)
SELECT	i0."id"
	, i0."transaction_id"
	, i0."position"
	, i0."is_coinbase"
	, i0."vout"
	, t2."trx_id"
	, o1."addresses"
	, o1."amount"
FROM "inputs" AS i0 
,LATERAL (SELECT * FROM "outputs" AS o1 WHERE o1."id" = i0."output_id" LIMIT 1) AS o1
,LATERAL (SELECT * "transactions" AS t2 WHERE t2."id" =  o1."transaction_id" LIMIT 1) AS t2
WHERE i0."transaction_id" IN (165237854, ...);
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370447
ora601
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nateless,

пробуй с подзапросами например :

SELECT * FROM

(SELECT * FROM inputs WHERE ...) sq1
JOIN t2
JOIN t3

Идеальный план для этого случая должен выглядеть как NL по индекс сканам.
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370466
nateless
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Получилось решить таким запросом, выбрал по индексам и быстро.

Код: plsql
1.
2.
3.
4.
5.
SELECT i0."id", i0."transaction_id", i0."position", i0."is_coinbase", i0."vout", t2."trx_id", o1."addresses", o1."amount"
FROM "inputs" AS i0
INNER JOIN "outputs" AS o1 ON o1."id" = i0."output_id"
INNER JOIN "transactions" AS t2 ON t2."id" = o1."transaction_id"
WHERE (i0."transaction_id" IN (SELECT ...))
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370512
Alexius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nateless,

сколько элементов у вас в in в исходном запросе? покажите выводы запросов

Код: sql
1.
2.
3.
select null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds from pg_stats where tablename = 'inputs' and attname = 'transaction_id';
explain select * from inputs;
explain analyze SELECT * FROM "inputs" AS i0 WHERE (i0."transaction_id" = ANY(ARRAY[165237854,.......])); 
...
Рейтинг: 0 / 0
Проходит полный Seq Scan вместо индекса.
    #39370613
ZiB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ZiB
Гость
nateless,

а если так?

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
set enable_nestloop = off;
SELECT i0."id", i0."transaction_id", i0."position", i0."is_coinbase", i0."vout", t2."trx_id", o1."addresses", o1."amount"
FROM "inputs" AS i0

INNER JOIN (SELECT ...) AS a ON a.? = i0."transaction_id"

INNER JOIN "outputs" AS o1 ON o1."id" = i0."output_id"
INNER JOIN "transactions" AS t2 ON t2."id" = o1."transaction_id";
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Проходит полный Seq Scan вместо индекса.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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