Gui*_*mas 6 postgresql performance postgresql-performance
使用 postgres 9.6,我不明白共享缓冲区如何与索引一起工作。
这意味着 shared_buffer 大小为 128 * 1024 * 1024 / 8192 = 16384 个块。
我创建了一个简单的表,其中包含随机数据和每列的索引。
DROP TABLE IF EXISTS sandbox;
CREATE TABLE sandbox AS
SELECT generate_series(1, 4000000) AS pk,
random() AS x;
CREATE INDEX ON sandbox(pk);
CREATE INDEX ON sandbox(x);
Run Code Online (Sandbox Code Playgroud)
我去了 4M 行。这是表和索引占用的大小:
postgres=# SELECT relname AS "relation",
pg_relation_size(C.oid) / 8192 AS "blocks",
pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE relname = 'sandbox' ;
relation | blocks | size
----------+--------+--------
sandbox | 21622 | 169 MB
Run Code Online (Sandbox Code Playgroud)
所以表大小 (169 Mb) 大于共享缓冲区 (128Mb)
我想检索条件为 x 的行。这将提取约 2%的数据。
postgres=# explain (ANALYZE, buffers, format text)
SELECT *
FROM sandbox
WHERE x < .02;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on sandbox (cost=24961.76..63250.42 rows=1333333 width=12) (actual time=29.059..347.203 rows=80218 loops=1)
Recheck Cond: (x < '0.02'::double precision)
Heap Blocks: exact=21113
Buffers: shared read=21335
-> Bitmap Index Scan on sandbox_x_idx (cost=0.00..24628.43 rows=1333333 width=0) (actual time=20.458..20.458 rows=80218 loops=1)
Index Cond: (x < '0.02'::double precision)
Buffers: shared read=222
Planning time: 0.293 ms
Execution time: 573.949 ms
Run Code Online (Sandbox Code Playgroud)
可以看出:
Bitmap Index Scan on sandbox_x_idx指示
read(来自磁盘)和没有hits(来自内存)。即使我重新运行查询,我也会得到相同的行为。现在我在 pk 上运行一个查询,我仍然获取 ~2% 的数据:
postgres=# explain (ANALYZE, buffers, format text)
SELECT *
FROM sandbox
WHERE pk < 80000;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on sandbox (cost=24961.76..63250.42 rows=1333333 width=12) (actual time=12.901..242.663 rows=79999 loops=1)
Recheck Cond: (pk < 80000)
Heap Blocks: exact=433
Buffers: shared hit=654
-> Bitmap Index Scan on sandbox_pk_idx (cost=0.00..24628.43 rows=1333333 width=0) (actual time=12.770..12.770 rows=79999 loops=1)
Index Cond: (pk < 80000)
Buffers: shared hit=221
Planning time: 0.082 ms
Execution time: 466.469 ms
Run Code Online (Sandbox Code Playgroud)
可以注意到: - 堆块要小得多:433,占总块的 2% 以上(21k) - 这些块被放入缓冲区,因为我们看到 hit
到目前为止我的理解是:
x。在每个块中有一行x < 0.02这样对吗?
我有兴趣选择条件为 on 的行x并且仍然受益于共享缓冲区。这意味着我需要块以某种方式依赖于x. 我怎样才能做到这一点?
其他想法?
小智 3
我同意@dezso,你应该开始分区,或者看看指令CLUSTER(https://www.postgresql.org/docs/9.4/static/sql-cluster.html)。如上所述,它将根据索引信息对数据进行物理重新排序,这似乎是您想要实现的目标。