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.1
和effective_cache_size
后结果是否会发生变化。
【参考方案1】:
如果A.VALUE >= 0.45
的数量或记录相对较少(比如少于总数的5%),A.VALUE
上的索引可以加快查询速度。此外,(A.VALUE, A.ID)
上的复合索引可能只允许对表 A 进行索引扫描。
【讨论】:
以上是关于PostgreSQL 连接性能的主要内容,如果未能解决你的问题,请参考以下文章
连接postgres特别消耗cpu资源而引发的PostgreSQL性能优化考虑
PostgreSQL 两个连接和它们之间的 NOT EQUAL 子句的性能