【问题标题】:What hashing algorithm/function is used by postgres for PARTITION BY HASHpostgres 使用什么散列算法/函数进行 PARTITION BY HASH
【发布时间】:2021-05-10 19:41:50
【问题描述】:

在 postgres 中,有一个基于 hash 的分区。但是postgres 并没有清楚地解释如何计算给定列值的散列值。

我搜索了 Postgres 文档,但一无所获。除了一些邮箱帖子,还有人提到hashtext()内部功能。有没有人知道用于散列值的实际函数(以及进一步使用模运算符)的任何信息?我的意思是 postgres 如何散列一个值,将其转换为 uint64 以进行最终的模运算。

更新: 通过阅读 postgres 源代码,我发现分区函数在尝试查找给定哈希的 uint64 值时使用这样的方法:

/*
 * DatumGetUInt64
 *      Returns 64-bit unsigned integer value of a datum.
 *
 * Note: this macro hides whether int64 is pass by value or by reference.
 */

#ifdef USE_FLOAT8_BYVAL
#define DatumGetUInt64(X) ((uint64) (X))
#else
#define DatumGetUInt64(X) (* ((uint64 *) DatumGetPointer(X)))
#endif

【问题讨论】:

标签: c postgresql


【解决方案1】:

使用的散列函数是散列索引运算符族的支持函数。您可以在pg_amproc系统目录中找到它们;加入pg_opfamily 并将查询限制为hash 访问方法的运算符族

此查询列出了每种类型的标准哈希支持函数:

SELECT DISTINCT
       ap.amproclefttype::regtype AS data_type,
       ap.amproc::regproc AS hash_function
FROM pg_amproc AS ap
   JOIN pg_opfamily AS of ON ap.amprocfamily = of.oid
   JOIN pg_am ON of.opfmethod = pg_am.oid
WHERE pg_am.amname = 'hash'
  AND ap.amprocnum = 1
ORDER BY amproclefttype::regtype::text;

函数应该无关紧要,但我理解你的好奇心。

请注意,除非您将分区放在不同的存储上以分散 I/O 负载,否则散列分区非常无用。

【讨论】:

  • 没用?因为我需要具有相同键的行始终位于同一个分区中,例如 Kafka 的主题分区。这不包括我可以使用列表或范围分区类型的任何基于日期或基于 ID 的逻辑
  • 为什么?如果您按键进行范围或列表分区,则同一键的行也将位于同一分区中。并且不需要仅仅因为表很大就进行分区。哈希分区实际上会减慢所有查询。
  • 如果我有数百万个密钥会怎样?它们不是预定义的,它们是由产生数百万个密钥的各种变量创建的。我的数据很大,我希望 postgres 查询计划程序只扫描一个(或最多几个)分区。这是否可能通过范围分区来实现(数百万个散列键)?
  • 我明白了,您的用例正在搜索具有“等于”条件的分区键,对吧?但是你真的想要对这样的搜索进行顺序扫描,即使它只在一个分区上?一旦你在列上有一个索引,查询实际上会随着分区而变慢(查询规划器的工作量更大)。
  • 不,如果您找到正确的列进行分区,这将非常有用。在我们的系统中,我们使用散列分区将更新时间从 40 秒缩短到不到一秒。
猜你喜欢
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-17
  • 2015-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多