postgresql - 对索引位集进行大量更新的最佳方法

标签 postgresql apache-spark database-performance jsonb

本题环境为PostgreSQL 9.6.5 on AWS RDS。

问题是关于一个包含以下逻辑数据模型的 3 亿行表的最佳模式设计和批量更新策略:

  • id:主键,最长40个字符的字符串
  • code:整数1-999
  • year: 整数年
  • flags:可变数量(1000+),每个都与一个名称相关联,随着时间的推移添加新的标志。理想情况下,应将标志视为具有三个值:不存在 (null)、on (true/1) 和 off (/0)。以额外更新为代价(见下文),可以将标志视为一个简单的位(打开或关闭,不存在)。 “开”值通常非常稀疏:< 1/1000。

查询通常涉及关于是否存在一个或多个标志(按名称)的 bool 表达式,偶尔也会涉及 codeyear

数据通过 Apache Spark 批量更新,即更新可以表示为平面文件,例如 COPY 格式,或表示为 SQL 操作。任何时候只有一个更新处于事件状态。 codeyear 很少更新。标志更新每次更新影响 1-5% 的行(3-15 百万行)。更新行可能包含所有标志及其值,仅更新“on”标志或仅包含其值已更改的标志。在前一种情况下,Spark 需要查询数据以获取标志的当前值。

更新期间会有少量读取负载。

问题是关于支持所描述的查询和更新的最佳架构和相关更新策略。

目前研究的一些评论:

  • 使用 1,000 多个 bool 列将创建非常高效的行表示,但除了一些 DDL 复杂性之外,还需要 1,000 多个索引。

  • 如果有一种索引单个位的方法,位串会很棒。此外,它们没有提供表示缺失标志的好方法。使用这种方法需要在标志名称和位 ID 之间维护一个查找表。如果需要,合并更新可与 || 一起使用,但考虑到 PostgreSQL 的 MVCC,与替换整行相比,仅更新标志似乎没有太大好处。

    <
  • JSONB 字段提供索引。它们还提供 null 表示,但这是有代价的:所有“关闭”的标志都需要显式设置,这会使字段变得非常大。如果我们忽略 null 表示,JSONB 字段会相对较小。为了进一步缩小它们,我们可以使用带有查找表的 1-3 个字符的短字段名称。相同的评论:与位串合并。

  • tsvector/tsquery:没有使用过这种数据类型的经验,但从理论上讲,它似乎是一组“on”标志的精确表示按名字。必须使用查找表将标记名称映射到 token ,并附加要求以确保不会因词干提取而发生冲突。

最佳答案

不要将标志存储在主表中。

假设主表名为data,定义如下内容:

CREATE TABLE flag_names (
   id smallint PRIMARY KEY,
   name text NOT NULL
);

CREATE TABLE flag (
   flagname_id smallint NOT NULL REFERENCES flag_names(id),
   data_id text NOT NULL REFERENCES data(id),
   value boolean NOT NULL,
   PRIMARY KEY (flagname_id, data_id)
);

如果创建了一个新标志,则在 flag_names 中插入一个新行。

如果标志设置为 TRUEFALSE,则在 flag 表中插入或更新一行。

加入 flagdata 来测试是否设置了某个标志。

关于postgresql - 对索引位集进行大量更新的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47404915/

相关文章:

postgresql - Ecto embeds_many 关联中的查询

postgresql - 事务中的 Postgres 锁

java - Spark v3.0.0 - 警告 DAGScheduler : broadcasting large task binary with size xx

mysql插入与更新性能

postgresql - 如何仅从 PostgreSQL 中的 varchar 列中选择整数值

sql - 多对多关系中的 AND 条件

hadoop - Spark Swift 集成 Parquet

json - 由于数据类型不匹配而获取 : argument 2 requires integral type error while parsing Json data Spark SQL

Mongodb:高获取数据库锁

java - Mysql和Java搜索匹配多列中的多个值