hstore 的用例

s.m*_*.m. 5 postgresql hstore postgresql-9.4

这是我第一次(我认为)有机会使用该hstore数据类型,但我想听听更有经验的人的意见,看看我的想法实际上是个好主意。

现在,我们在这个 Web 应用程序中以 XML 文件的形式导入工资数据,它看起来大致像这个简化版本:

<Company>
    <Employee>
        <LastName>Smith</LastName>
        <FirstName>John</LastName>
        <HourlyWage>9999.99</HourlyWage>
        <!-- several other hundreds of tags -->
    </Employee>
    <Employee>
        <!-- ... -->
    </Employee> 
</Company>
Run Code Online (Sandbox Code Playgroud)

每个员工都携带着极其详细的信息,当我说“其他数百个标签”时,是因为它们通常在 800 个到 1400 个以上之间。而且这是每个月的。除了一组核心标签之外,每个员工都可以有不同的组合,因此我上面给出的数字非常波动但非常现实。

现在,部分数据是通过一个漫长、缓慢且非常复杂的过程导入的,而且我观察到,随着频率的增加,我们发现自己说“天哪,如果我们总是导入那个特定标签就好了! ”。

虽然导入过程是高度可配置的,但仅针对一小部分数据运行它是缓慢的、不切实际的并且非常痛苦。从现在开始,添加导入假设的新标签所需的任何自定义操作要容易得多,但是对于构建历史数据(就像我们总是导入它一样),它很混乱且容易出错。

作为额外的好处,这项任务总是落在这两个人身上,而我就是其中之一,我很想让我们的生活变得更简单。

这就是为什么我正在考虑编写一个快速工具,在夜间打开这些 XML 文件,并为每个月和每个员工创建一个记录,其中包含包含hstore该月所有员工标签的列。

作为 的绝对初学者hstore,这在我看来是一个非常好的用例,特别是如果我们考虑到:

  • 由于每个员工的标签可能不同,因此这本质上是无模式数据。

  • 将标签存储为 EAV(每个标签一行)对于一家拥有 200 名员工的公司来说意味着每月大约 24 万行(每年 280 万行)。当然,没有什么可担心的,但顾客并不只有一个。其中一家拥有超过 7,000 名员工(每年将有 1 亿条记录)。

  • 这些数据只需要被读取,而无需更改。另外,无论如何,它甚至不会被经常阅读。

  • 我真的不关心或不知道任何给定标签的含义。我只是想存储它以供将来使用,告诉我需要哪一个是领域专家的工作。再次强调无模式。

我要设计的表格看起来有点像这样:

- id bigserial
- user_id
- file_timestamp (it's embedded on the name of the file)
- employee_id_1 varchar
- employee_id_2 varchar
- month date
- file_id (id of the XML file, it gets logged in a table before being imported)
- tags hstore
Run Code Online (Sandbox Code Playgroud)

(employee_id 1 和 2 中,前者看起来像美国 SSN,后者是从我们的薪资应用程序分配的)。

我还会在 上创建一个唯一索引(user_id, employee_id_1, employee_id_2, month, file_id)。不能 100% 确定列的顺序,但我认为它可以适应大多数SELECT想要逐步缩小数据范围的情况。

另外,我不想为每个客户复制该表,并且我不希望或不需要它对用户可见。我会创建一个专用模式并将其粘贴在那里,如果我想在将来的某个时候对其进行分区,这会更容易管理。这将是一个巨大的表(不是因为行数太多,而是因为每行所需的空间),但保留其自己的模式也意味着更容易从大多数备份中排除。另外,无论如何我们都会保留原始的 XML 文件,因此如果出现问题,重建起来并不困难。

通过这样的设计,使用一堆临时的一次性查询生成历史数据看起来就像是小孩子的游戏。

但由于我不是专家,我想知道是否:

  1. 这实际上是一个很好的用例hstore
  2. 我的设计有明显的缺陷
  3. hstore进入场景时需要注意一些事项,以免陷入困境
  4. 由于标签数量相当大,但每行的数量仍然不多,是否值得在hstore键上创建索引?

Eva*_*oll 2

在您工作的范围内。我认为 JSONB 是理想的。它处理深度嵌套的结构和带有数组键的结构。它也是标准化的并且在 sql2016 的规范中。

此外,正如我在这里回答的那样,有一个扩展可以帮助您解决空间消耗问题,称为ZSON

ZSON是用于透明 JSONB 压缩的 PostgreSQL 扩展。压缩基于特定 JSONB 文档中最常用的字符串共享字典(不仅是键,还包括值、数组元素等)。

在某些情况下,ZSON 可以节省一半的磁盘空间,并为您提供大约 10% 的 TPS。内存也被保存。请参阅 docs/benchmark.md。不过,一切都取决于您的数据和工作量。不要相信任何基准测试,重新检查您的数据、配置、硬件、工作负载和 PostgreSQL 版本的所有内容。

您可能想研究一下 ZSON。