PostgreSQL.Улучшить индексы - PullRequest
0 голосов
/ 22 мая 2018

У меня есть следующая структура:

create table bitmex
(
  timestamp timestamp with time zone not null,
  symbol    varchar(255)             not null,
  side      varchar(255)             not null,
  tid       varchar(255)             not null,
  size      numeric                  not null,
  price     numeric                  not null,
  constraint bitmex_tid_symbol_pk
  primary key (tid, symbol)
);

create index bitmex_timestamp_symbol_index  on bitmex (timestamp, symbol);
create index bitmex_symbol_index  on bitmex (symbol);

Мне нужно знать точное значение количества каждый раз.Таким образом, reltuples нельзя использовать.

Таблица содержит более 45 000 000 строк.

Running

explain analyze select count(*) from bitmex where symbol = 'XBTUSD';

дает

Finalize Aggregate  (cost=1038428.56..1038428.57 rows=1 width=8)
  ->  Gather  (cost=1038428.35..1038428.56 rows=2 width=8)
        Workers Planned: 2
        ->  Partial Aggregate  (cost=1037428.35..1037428.36 rows=1 width=8)
              ->  Parallel Seq Scan on bitmex  (cost=0.00..996439.12 rows=16395690 width=0)
                    Filter: ((symbol)::text = 'XBTUSD'::text)

Running

explain analyze select count(*) from bitmex;

дает

Finalize Aggregate  (cost=997439.34..997439.35 rows=1 width=8) (actual time=6105.463..6105.463 rows=1 loops=1)
  ->  Gather  (cost=997439.12..997439.33 rows=2 width=8) (actual time=6105.444..6105.457 rows=3 loops=1)
        Workers Planned: 2
        Workers Launched: 2
        ->  Partial Aggregate  (cost=996439.12..996439.14 rows=1 width=8) (actual time=6085.960..6085.960 rows=1 loops=3)
              ->  Parallel Seq Scan on bitmex  (cost=0.00..954473.50 rows=16786250 width=0) (actual time=0.364..4342.460 rows=13819096 loops=3)
Planning time: 0.080 ms
Execution time: 6108.277 ms

Почему он не использовал индексы?Спасибо

1 Ответ

0 голосов
/ 23 мая 2018

Если необходимо просмотреть все строки, сканирование индекса обходится дешевле, только если с таблицей не нужно обращаться к большинству значений, найденных в индексе.

Из-за того, как организован PostgreSQL,таблицу нужно посетить, чтобы определить, видима ли найденная в индексе запись или нет.Этот шаг можно пропустить, если вся страница помечена как «видимая» на карте видимости таблицы.

Чтобы обновить карту видимости, запустите на таблице VACUUM.Возможно, тогда будет использоваться сканирование только по индексу .

Но подсчет количества строк в таблице обходится никогда дешево, даже при сканировании индекса.Если вам нужно делать это часто, хорошей идеей будет иметь отдельную таблицу, которая содержит только счетчик количества строк.Затем вы можете написать триггеры, которые обновляют счетчик всякий раз, когда строки вставляются или удаляются.

Это замедлит производительность во время INSERT и DELETE, но вы можете считать строки с молниеносной скоростью.

...