【问题标题】:Postgres not very fast at finding unique values in table with about 1.3 billion rowsPostgres 在大约 13 亿行的表中查找唯一值的速度不是很快
【发布时间】:2020-11-09 00:44:10
【问题描述】:

所以我有一个(记录的)表,其中包含 A、B 两列,其中包含文本。 它们基本上包含相同类型的信息,因为数据来自哪里,所以只有两列。

我想要一个包含所有唯一值的表(所以我将列设为主键),而不关心列。但是当我要求 postgres 做时

insert into new_table(value) select A from old_table on conflict (value) 什么都不做; (稍后对 B 列进行同样的操作)

它使用 1 个 cpu 核心,并且仅以大约 5 MB/s 的速度从我的 SSD 读取数据。几个小时后我停止了它。

我怀疑这可能是因为 b-tree 很慢,所以我在新表的唯一属性上添加了一个 hashindex。但它仍然最大程度地使用 1 个核心,并以每秒 5 MB/s 的速度从 ssd 读取数据。我的 java 程序可以设置至少 150 MB/s,所以 postgres 应该比 5 MB/s 快,对吧?我已经分析了我的旧表,并为我的新表取消了记录以便更快地插入,但它仍然使用 1 个核心并且读取速度非常慢。

如何解决这个问题?

编辑:这是对上述查询的解释。似乎 postgres 正在使用它为主键创建的 b-tree 而不是我的(快得多,不是吗??)哈希索引。

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)

【问题讨论】:

    标签: postgresql performance indexing unique


    【解决方案1】:

    ON CONFLICT 机制主要用于解决并发引发的冲突。您可以在这样的“静态”情况下使用它,但其他方法会更有效。

    首先只插入不同的值:

    insert into new_table(value) 
        select A from old_table union
        select B from old_table 
    

    为提高性能,在填充表之前不要添加主键。并将 work_mem 设置为您可信的最大值。

    我的 java 程序可以设置至少 150 MB/s,

    这完全在内存中使用哈希集。 PostgreSQL 索引是基于磁盘的结构。它们确实受益于缓存,但仅此而已,并且取决于您尚未告诉我们的硬件和设置。

    似乎 postgres 正在使用它为主键创建的 b-tree 而不是我的(快得多,不是吗??)哈希索引。

    它只能使用定义约束的索引,即btree索引,因为哈希索引不支持主键约束。您可以使用哈希索引定义 EXCLUDE 约束,但这只会使其变慢。总的来说,散列索引并不比 PostgreSQL 中的 btree 索引“快得多”。

    【讨论】:

    • i7-8750H 6 核 2.2 Ghz 基本超线程,16 GB RAM 2666,在基准测试期间具有 3 GB 读写能力的 SSD,大量可用空间,GPU 没关系我想?
    • 对,GPU 无所谓。核心计数也不支持,因为并行查询当前不支持 INSERT 语句。结果集有多少行? 16GB 可能不足以将它们全部散列,除非输入大部分是重复的。
    • 结果集比 1.083.000.000 多一点
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 2018-11-16
    • 2016-10-03
    相关资源
    最近更新 更多