【发布时间】:2017-06-19 01:30:07
【问题描述】:
我们在我们的一个数据库表中使用 Postgres jsonb 类型。表结构如下:
CREATE TABLE T (
id UUID NOT NULL PRIMARY KEY,
payload JSONB
);
CREATE INDEX ON T USING gin (payload jsonb_path_ops);
Payload 是一个复杂的 json 字符串。下面是一个例子:
{
"business": {
"taxId": "626642071",
"legalName": "Jon's Deli",
"phoneNumbers": [
{
"phoneType": "Business",
"telephoneNumber": "8384407555"
},
{
"phoneType": "Work",
"telephoneNumber": "6032255248"
}
],
"addresses": [
{
"city": "San Francisco",
"state": "CA",
"postalCode": "94101",
"countryCode": "USA",
"addressLine1": "123 Market St"
}
]
},
"stakeholders": [
{
"person": {
"taxId": "540646815",
"firstName": "GdXFouh",
"lastName": "IlUAcgCGz",
"dateOfBirth": "1980-12-11",
"emailAddress": "jywxsijgix@qaqmlz.com",
"phoneNumbers": [
{
"phoneType": "Mobile",
"telephoneNumber": "4901371573"
}
],
"addresses": [
{
"city": "San Francisco",
"state": "CA",
"postalCode": "94101",
"countryCode": "USA",
"addressLine1": "123 Market St"
}
]
}
}
]
}
注意phoneNumbers、addresses和stakeholders是数组,这意味着数组中可以有多个元素。
我尝试在表中插入一百万行。 payload 的每个字段都是随机生成的。最初,测试程序运行得非常快。但是插入大约800,000行后,每1000行就卡住了——插入1000行,然后测试程序挂了2分钟,然后又回来插入1000行,...
我们怀疑这是由于大量 jsonb 索引更新造成的。因为单行的索引中有很多字段要更新。我们只是想确认是否有人遇到过同样的问题。
实际上我们不需要索引整个payload 列。仅需要某些字段:business->taxId、business->phoneNumbers-> telephoneNumber、stakeholders->person->taxId 和 stakeholders->person->emailAddress。
我尝试了以下两个索引:
CREATE INDEX ON T USING gin ((payload->'business'->'taxId') jsonb_path_ops);
CREATE INDEX ON T USING gin ((payload ->'stakeholders'->'person'->'taxId') jsonb_path_ops);
并运行两条语句:
explain select * from T where payload->'business'->'taxId' @> '"123456789"'; (1)
explain select * from T where payload->'stakeholders'->'person'->'taxId' @> '"123456789"'; (2)
第一条语句是使用索引。但是第二个是进行非常慢的全表扫描。这就是我们转向索引整个payload 列的原因。
欢迎提出任何建议。
顺便说一句,我们使用的是 Postgres 9.5.4。
【问题讨论】:
-
如果该有效负载要保持一致,您应该考虑将其转换为真正的模式。 Postgres 这样会更有效率。当您不确定结构是什么或结构稀疏时,请保留 JSONB。人员、地址、电话号码、企业和利益相关者就是您的表格。
-
payload 的架构可能会在不久的将来更改。这就是为什么我们将其保存为 json,而不是以标准化的方式进行。
标签: json performance postgresql indexing jsonb