Postgres 在 table 中找到大约 13 亿行的唯一值不是很快
Postgres not very fast at finding unique values in table with about 1.3 billion rows
所以我有一个(已记录)table,其中包含两列 A、B,其中包含文本。
它们基本上包含相同类型的信息,只是两列,因为数据来自哪里。
我想要一个包含所有唯一值的 table(因此我将该列作为主键),而不关心该列。但是当我要求 postgres 做
insert into new_table(value) select A from old_table on conflict (value) 什么都不做; (稍后对 B 列进行同样的操作)
它使用了 1 个 cpu 核心,并且只从我的 SSD 读取大约 5 MB/s。几个小时后我停止了它。
我怀疑这可能是因为 b-tree 很慢,所以我在我的新 table 中的唯一属性上添加了一个 hashindex。但它仍然最大程度地使用 1 个核心,并以每秒仅 5 MB/s 的速度从 ssd 读取数据。我的 java 程序可以哈希设置至少 150 MB/s,所以 postgres 应该比 5 MB/s 快得多,对吗?我已经分析了我的旧 table 并且我将我的新 table 取消记录以便更快地插入,但它仍然使用 1 个内核并且读取速度非常慢。
如何解决这个问题?
编辑:这是对上述查询的解释。好像 postgres 正在使用它为主键创建的 b 树而不是我的(快得多,不是吗??)哈希索引。
Insert on users (cost=0.00..28648717.24 rows=1340108416 width=14)
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: users_pkey
-> Seq Scan on games (cost=0.00..28648717.24 rows=1340108416 width=14)
ON CONFLICT
机制主要是为了解决并发引起的冲突。您可以在像这样的“静态”情况下使用它,但其他方法会更有效。
首先只插入不同的值:
insert into new_table(value)
select A from old_table union
select B from old_table
为了提高性能,在填充 table 之前不要添加主键。并将 work_mem 设置为您可以相信的最大值。
My java program can hashset that at at least 150 MB/s,
这是完全在内存中使用哈希集。 PostgreSQL 索引是基于磁盘的结构。它们确实受益于缓存,但这仅到此为止,并且取决于您尚未告诉我们的硬件和设置。
Seems like postgres is using the b-tree it created for the primary key instead of my (much faster, isn't it??) Hash index.
只能使用定义约束的索引,即btree索引,因为hash索引不支持主键约束。您可以使用散列索引定义 EXCLUDE 约束,但这只会使其变慢。通常,散列索引不是比 PostgreSQL 中的 btree 索引“快得多”。
所以我有一个(已记录)table,其中包含两列 A、B,其中包含文本。 它们基本上包含相同类型的信息,只是两列,因为数据来自哪里。
我想要一个包含所有唯一值的 table(因此我将该列作为主键),而不关心该列。但是当我要求 postgres 做
insert into new_table(value) select A from old_table on conflict (value) 什么都不做; (稍后对 B 列进行同样的操作)
它使用了 1 个 cpu 核心,并且只从我的 SSD 读取大约 5 MB/s。几个小时后我停止了它。
我怀疑这可能是因为 b-tree 很慢,所以我在我的新 table 中的唯一属性上添加了一个 hashindex。但它仍然最大程度地使用 1 个核心,并以每秒仅 5 MB/s 的速度从 ssd 读取数据。我的 java 程序可以哈希设置至少 150 MB/s,所以 postgres 应该比 5 MB/s 快得多,对吗?我已经分析了我的旧 table 并且我将我的新 table 取消记录以便更快地插入,但它仍然使用 1 个内核并且读取速度非常慢。
如何解决这个问题?
编辑:这是对上述查询的解释。好像 postgres 正在使用它为主键创建的 b 树而不是我的(快得多,不是吗??)哈希索引。
Insert on users (cost=0.00..28648717.24 rows=1340108416 width=14)
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: users_pkey
-> Seq Scan on games (cost=0.00..28648717.24 rows=1340108416 width=14)
ON CONFLICT
机制主要是为了解决并发引起的冲突。您可以在像这样的“静态”情况下使用它,但其他方法会更有效。
首先只插入不同的值:
insert into new_table(value)
select A from old_table union
select B from old_table
为了提高性能,在填充 table 之前不要添加主键。并将 work_mem 设置为您可以相信的最大值。
My java program can hashset that at at least 150 MB/s,
这是完全在内存中使用哈希集。 PostgreSQL 索引是基于磁盘的结构。它们确实受益于缓存,但这仅到此为止,并且取决于您尚未告诉我们的硬件和设置。
Seems like postgres is using the b-tree it created for the primary key instead of my (much faster, isn't it??) Hash index.
只能使用定义约束的索引,即btree索引,因为hash索引不支持主键约束。您可以使用散列索引定义 EXCLUDE 约束,但这只会使其变慢。通常,散列索引不是比 PostgreSQL 中的 btree 索引“快得多”。