我们在我们的数据库表中使用了Postgres jsonb类型。表结构如下所示: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": "[email protected]",
"phoneNumbers": [
{
"phoneType": "Mobile",
"telephoneNumber": "4901371573"
}
],
"addresses": [
{
"city": "San Francisco",
"state": "CA",
"postalCode": "94101",
"countryCode": "USA",
"addressLine1": "123 Market St"
}
]
}
}
]
}
注意phoneNumbers
,addresses
和stakeholders
是数组,这意味着可以有阵列中的多个元素。
我尝试在表中插入一百万行。生成的每个字段随机。最初测试程序运行速度非常快。但插入大约800,000行后,每隔1000行就卡住 - 插入1000行,然后测试程序挂起2分钟,然后返回并插入另外1000行,...
我们怀疑这个是由大量的jsonb索引更新引起的。因为单行索引中有很多字段需要更新。我们只是想确认是否有人遇到同样的问题。
其实我们并不需要索引整个列。只需要某些字段: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)
第一个语句使用索引。但第二个是做一个非常缓慢的全表扫描。这就是为什么我们转向索引整个列。
任何建议是值得欢迎的。
顺便说一句,我们正在使用Postgres 9.5.4。
如果有效载荷将是一致的,你应该考虑把它变成一个真正的模式。 Postgres将会更加高效。当你不确定结构是什么时,或者结构是否稀疏时,保留JSONB。人们,地址,电话号码,企业和利益相关者是你的桌子。 – Schwern
有效载荷的模式可能会在不久的将来发生变化。这就是为什么我们将它保存为json,而不是以规范化的方式进行。 –