我們在我們的數據庫表中使用了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,而不是以規範化的方式進行。 –