PostgreSQL。改善指标
PostgreSQL. Improve indexes
我有以下结构:
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 不可用。
table 有超过 45,000,000 行。
运行
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)
运行
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
为什么没有使用索引?
谢谢
如果必须访问所有行,只有在 table 不必为索引中找到的大多数值查询时,索引扫描才会更便宜。
由于 PostgreSQL 的组织方式,必须访问 table 以确定在索引中找到的条目是否可见。如果整个页面在 table.
的 可见性映射 中标记为“可见”,则可以跳过此步骤
要更新可见性地图,运行 VACUUM
table。也许然后 index only scan 将被使用。
但是计算 table 中的行数永远不会便宜,即使使用索引扫描也是如此。如果您需要经常这样做,最好有一个单独的 table,它只包含一个行数计数器。然后您可以编写触发器,在插入或删除行时更新计数器。
这会降低 INSERT
和 DELETE
期间的性能,但您可以以闪电般的速度计算行数。
我有以下结构:
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 不可用。
table 有超过 45,000,000 行。
运行
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)
运行
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
为什么没有使用索引? 谢谢
如果必须访问所有行,只有在 table 不必为索引中找到的大多数值查询时,索引扫描才会更便宜。
由于 PostgreSQL 的组织方式,必须访问 table 以确定在索引中找到的条目是否可见。如果整个页面在 table.
的 可见性映射 中标记为“可见”,则可以跳过此步骤要更新可见性地图,运行 VACUUM
table。也许然后 index only scan 将被使用。
但是计算 table 中的行数永远不会便宜,即使使用索引扫描也是如此。如果您需要经常这样做,最好有一个单独的 table,它只包含一个行数计数器。然后您可以编写触发器,在插入或删除行时更新计数器。
这会降低 INSERT
和 DELETE
期间的性能,但您可以以闪电般的速度计算行数。