【发布时间】:2020-01-29 18:44:25
【问题描述】:
我正在运行 Postgres 11。 我有一个包含 1.000.000(100 万)行的表,每行的大小为 40 个字节(它包含 5 列)。这等于 40MB。
当我执行时(通过 DBeaver、DataGrid 等直接在 DB 上执行-不通过 Node、Python 等调用):
SELECT * FROM TABLE
第一次需要40秒(即使是第一次也不是很慢)。
我的表的 CREATE 语句:
CREATE TABLE public.my_table_1 (
c1 int8 NOT NULL GENERATED ALWAYS AS IDENTITY,
c2 int8 NOT NULL,
c3 timestamptz NULL,
c4 float8 NOT NULL,
c5 float8 NOT NULL,
CONSTRAINT my_table_1_pkey PRIMARY KEY (id)
);
CREATE INDEX my_table_1_c3_idx ON public.my_table_1 USING btree (c3);
CREATE UNIQUE INDEX my_table_1_c2_idx ON public.my_table_1 USING btree (c2);
在 5 个随机表上:EXPLAIN (ANALYZE, BUFFERS) select * from [table_1...2,3,4,5]
Seq Scan on table_1 (cost=0.00..666.06 rows=34406 width=41) (actual time=0.125..7.698 rows=34406 loops=1)
Buffers: shared read=322
Planning Time: 15.521 ms
Execution Time: 10.139 ms
Seq Scan on table_2 (cost=0.00..9734.87 rows=503187 width=41) (actual time=0.103..57.698 rows=503187 loops=1)
Buffers: shared read=4703
Planning Time: 14.265 ms
Execution Time: 74.240 ms
Seq Scan on table_3 (cost=0.00..3486217.40 rows=180205440 width=41) (actual time=0.022..14988.078 rows=180205379 loops=1)
Buffers: shared hit=7899 read=1676264
Planning Time: 0.413 ms
Execution Time: 20781.303 ms
Seq Scan on table_4 (cost=0.00..140219.73 rows=7248073 width=41) (actual time=13.638..978.125 rows=7247991 loops=1)
Buffers: shared hit=7394 read=60345
Planning Time: 0.246 ms
Execution Time: 1264.766 ms
Seq Scan on table_5 (cost=0.00..348132.60 rows=17995260 width=41) (actual time=13.648..2138.741 rows=17995174 loops=1)
Buffers: shared hit=82 read=168098
Planning Time: 0.339 ms
Execution Time: 2730.355 ms
当我将 LIMIT 1.000.000 添加到 table_5 时(它包含 170 万行)
Limit (cost=0.00..19345.79 rows=1000000 width=41) (actual time=0.007..131.939 rows=1000000 loops=1)
Buffers: shared hit=9346
-> Seq Scan on table_5(cost=0.00..348132.60 rows=17995260 width=41) (actual time=0.006..68.635 rows=1000000 loops=1)
Buffers: shared hit=9346
Planning Time: 0.048 ms
Execution Time: 164.133 ms
当我在 2 个日期之间添加 WHERE 子句时(我使用 DataDog 软件监控下面的查询,结果在这里(获取时最大~ 31K 行/秒):https://www.screencast.com/t/yV0k4ShrUwSd):
Seq Scan on table_5 (cost=0.00..438108.90 rows=17862027 width=41) (actual time=0.026..2070.047 rows=17866766 loops=1)
Filter: (('2018-01-01 00:00:00+04'::timestamp with time zone < matchdate) AND (matchdate < '2020-01-01 00:00:00+04'::timestamp with time zone))
Rows Removed by Filter: 128408
Buffers: shared hit=168180
Planning Time: 14.820 ms
Execution Time: 2673.171 ms
所有表的 c3 列都有唯一索引。
数据库的大小总共约为 500GB。 服务器有 16 个核心和 112GB M2 内存。
我尝试优化 Postgres 系统变量 - 例如:WorkMem(1GB)、shared_buffer(50GB)、effective_cache_size (20GB) - 但它似乎没有改变任何东西(我知道设置已应用 - 因为我可以看到服务器分配的空闲内存量有很大差异)。
我知道数据库太大,所有数据都无法存储在内存中。但是我可以做些什么来提高查询的性能/速度?
【问题讨论】:
-
提示:如果你使用
CreatedDate BETWEEN ... AND ...而不是这样表达它会更有意义。 -
A) 听起来您确实需要该列上的索引。 B) 使用ISO 8601 date format,如
YYYY-MM-DD。这些可以被索引。您在此处的日期无法排序,对 Postgres 毫无意义。你在这里的方式是 11 月在 2 月之前,但在 1 月之后,或者如果这是 DD-MM-YYYY 远不清楚,那么 1 月 11 日可能会在 1 月 2 日之前。 -
M2内存?你的意思是m.2?
-
你能分享
CREATE TABLE的声明吗? -
@tadman PostgreSQL 可以毫无问题地理解“01-01-2019”作为日期的含义,并将根据该理解使用索引。它参考 DateStyle 来决定 MDY 和 DMY。
标签: postgresql