如何在PostgreSQL中存储和索引JSON数据以获得更好的搜索性能?

1cklez4t  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(160)

我读过几篇关于PostgreSQL数据类型,索引和全文搜索的文章。然而,我仍然对实现以下要求的最有效方法有疑问。我想发布一个单独的问题来询问索引特定数据的最佳方法,但我决定发布一个问题来提供更多的上下文。

1.我需要存储来自其他应用程序的日志消息,其格式如下:

{
    "ID": 5856,
    "TimeStamp": "2023-10-28T13:32:43Z",
    "Level": "Info",
    "Message": "Some system generated message about the current record",
    "User": "John Lennon",
    "Cube": "Sales Actuals",
    "Tuple": [
        "2023-Nov",
        "Canada",
        ...,
        "Product 123",
        "Units sold"
    ],
    "OldValue": "237",
    "NewValue": "280"
}

字符串

Tuple是给定多维Cube的坐标(或简单的元素)数组。一个Cube可以有2个或更多维度,因此一个Tuple可以有2个或更多元素。
2.我们预计有相当大的数据量,从1000万到1亿条记录,甚至更多
3.记录应优化为下一个条件搜索,可同时应用一个或多个条件:

  • 时间戳:DATE 1和DATE 2之间,即2023-10- 27 T00:00:00 Z和2023-11- 05 T23:59:59 Z之间
  • 级别:精确值,即“信息”
  • 用户:确切的值,即“John Lennon”
  • 立方:精确值,即“实际销售额”
  • 元组:多模式搜索,不区分大小写,即:contains(“2023”)& contains(“canad”)& contains(“Units sold”)
  • 留言:全文检索
  • OldValue:全文搜索
  • NewValue:全文检索

我们可以通过组合字段进行1次全文搜索:Tuple.join(““)+ Message + OldValue + NewValue

4.搜索结果需要以JSON格式反馈到我的前端:

我们可以创建额外的列来构建索引或优化搜索性能,但最终,查询应该返回从资源应用程序检索到的原始JSON记录(键顺序和白色空格无关紧要)。
我使用Python从源应用程序中提取日志记录,并将其插入到PostgreSQL中,这样我就可以在需要时处理数据。
我需要帮助设计表和索引,特别是我试图弄清楚:
我是否应该将记录存储为单一的JSONB格式?我是否应该索引查询过滤器中需要使用的每个字段?将某些字段存储为单独的列并对其进行索引是否会带来性能差异?
我很感激任何关于优化性能的建议。

inb24sb2

inb24sb21#

如果你需要检索的JSON数据与源代码中写的完全一样,那么你需要使用json,而不是jsonb。jsonb会规范化像空格和对象键的顺序这样的东西,所以不能完全复制原始数据。我猜这取决于要求有多严格。也许你只是说输出需要是JSON,而不是它需要在字节上与输入相同。
你可以将不同的单值字段从json中复制到表中它们自己的列中。这将使查询更好看,但也会导致更高的存储空间,因为数据不必要地重复。我通常更喜欢使用功能/操作索引而不是重复数据。
所以你可以把索引

create index  on j ((data->>'Level'));

字符串
然后查询where data->>'Level' = 'Info'
而不是使用单独的列并使用清理器where level='Info'进行查询。
您可能需要定义一些帮助函数来处理“TimeStamp”,因为文本到timestamptz的转换不是不可变的,因此不能直接在索引定义中使用。
对于“Tuple”,您可以构建一个函数式杜松子酒索引,例如

create index on j using gin ( jsonb_to_tsvector('english', (data->'Tuple')::jsonb,'"String"'));


如果相等性测试的内容通常一起使用,并且没有一个单独使用时具有高度选择性,那么您可能需要一些多列索引。但是使用操作索引时的注意事项与使用真正的列索引时没有什么不同,它只是额外的麻烦:

create index on j ((data->>'Level'),(data->>'User'));

相关问题