PostgreSQL 连接性能

Posted

技术标签:

【中文标题】PostgreSQL 连接性能【英文标题】:PostgreSQL join performance 【发布时间】:2014-01-23 16:05:08 【问题描述】:

我在 PostgreSQL 9.3 数据库中有两个表:

TableA(ID numeric, VALUE numeric(5,4)) - 大约 100 万条记录。

TableB(ID numeric, field2 .. fieldN) - 大约 500 万条记录。

我正在尝试按 ID 字段在 TableA 和 TableB 之间进行简单的 JOIN,按字段 VALUE 过滤。 虽然 VALUE 可以有 4 位小数,但应用的过滤器只能有 2 位小数。

我的SQL是这样的(0.45是过滤参数,0.00到1.00之间):

SELECT A.ID, A.VALUE, B.a_lot_of_fields_here
FROM TableA A, TableB B
WHERE A.ID = B.ID
and A.VALUE >= 0.45

两个 ID(A.ID、B.ID)都是 PK。我想知道我是否可以做一些事情来加快 SQL 的速度。有什么建议吗?

这是查询解释计划:

"Hash Join  (cost=22205.73..310550.04 rows=1167395 width=105)"
"  Hash Cond: ((a.id)::text = (b.id)::text)"
"  ->  Seq Scan on tablea a  (cost=0.00..140163.94 rows=3557794 width=80)"
"  ->  Hash  (cost=17404.18..17404.18 rows=248284 width=25)"
"        ->  Bitmap Heap Scan on tableb b  (cost=4652.63..17404.18 rows=248284 width=25)"
"              Recheck Cond: (value >= 0.1)"
"              ->  Bitmap Index Scan on index_test  (cost=0.00..4590.56 rows=248284 width=0)"
"                    Index Cond: (value >= 0.1)"

还有一个带有 ANALYZE/BUFFERS 的

"Hash Join  (cost=22205.73..315312.78 rows=1398289 width=109) (actual time=2065.165..12794.984 rows=1267024 loops=1)"
"  Hash Cond: ((a.id)::text = (b.id)::text)"
"  Buffers: shared hit=177 read=71080 written=47217, temp read=47454 written=47424"
"  ->  Seq Scan on tablea a  (cost=0.00..107631.74 rows=4261474 width=84) (actual time=0.014..2815.098 rows=3557794 loops=1)"
"        Buffers: shared hit=175 read=64842 written=43965"
"  ->  Hash  (cost=17404.18..17404.18 rows=248284 width=25) (actual time=2047.615..2047.615 rows=248617 loops=1)"
"        Buckets: 2048  Batches: 16  Memory Usage: 901kB"
"        Buffers: shared hit=2 read=6238 written=3252, temp written=1319"
"        ->  Bitmap Heap Scan on tableb b  (cost=4652.63..17404.18 rows=248284 width=25) (actual time=491.395..1914.202 rows=248617 loops=1)"
"              Recheck Cond: (value >= 0.1)"
"              Buffers: shared hit=2 read=6238 written=3252"
"              ->  Bitmap Index Scan on index_test  (cost=0.00..4590.56 rows=248284 width=0) (actual time=448.286..448.286 rows=248617 loops=1)"
"                    Index Cond: (value >= 0.1)"
"                    Buffers: shared read=682"
"Total runtime: 12905.306 ms"

(On explain.depesz.com)

现在我正在处理 A.ID 和 B.ID 字段:它们是文本字段...我将把文本编码为整数,看看使用这种方法可以获得多少性能提升。

Postgres 配置资料:

我查看了 postresql.conf。我的所有参数都具有默认值:(-我没有调整它们的知识-。只有一个被编辑(由系统管理员):

shared_buffers = 128MB

【问题讨论】:

你的表有什么索引? TableA.Value 上的索引会有所帮助。由于TableB.ID 是聚集索引,因此您不需要对此表进行任何更改。 两个表的 ID 都有索引(它们是 PK)。应用过滤器 0.1 的连接,返回 1.250.000 条记录大约需要 9 秒。看起来是一个可以改进的时间? 我按照 GarethD 的建议创建了索引,但没有任何改进:( 我很想看看在为您的系统正确设置random_page_cost = 1.1effective_cache_size 后结果是否会发生变化。 【参考方案1】:

如果A.VALUE >= 0.45 的数量或记录相对较少(比如少于总数的5%),A.VALUE 上的索引可以加快查询速度。此外,(A.VALUE, A.ID) 上的复合索引可能只允许对表 A 进行索引扫描。

【讨论】:

以上是关于PostgreSQL 连接性能的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 条件连接的性能 - 查询优化

连接postgres特别消耗cpu资源而引发的PostgreSQL性能优化考虑

PostgreSQL 两个连接和它们之间的 NOT EQUAL 子句的性能

连接postgres特别消耗cpu资源而引发的PostgreSQL性能优化考虑

PostgreSQL的默认连接池限制是多少?

Postgresql 中不可预测的查询性能