PostgreSQL是不是你的下一個JSON資料庫?

來源:互聯網
上載者:User

標籤:

根據Betteridge定律(任何頭條的設問句可以用一個詞來回答:不是),除非你的JSON資料很少修改,並且查詢很多。

最新版的PostgreSQL添加更多對JSON的支援,我們曾經問過PostgreSQL是否可以替換MongoDB作為JSON資料庫,答案顯而易見,但我們更希望的是,啊哈,這個問題由讀者來問了。

“PostgreSQL不是已經有一些json的支援了嗎?”

是的,在PostgreSQL 9.4之前的版本也有JSON 資料類型了,你可以這樣:

CREATE TABLE justjson ( id INTEGER, doc JSON)>INSERT INTO justjson VALUES ( 1, ‘{    "name":"fred",    "address":{        "line1":"52 The Elms",        "line2":"Elmstreet",        "postcode":"ES1 1ES"        }    }‘);

儲存了JSON的原始文本到資料庫,包括空白行和鍵順序及重新的鍵,我們來查看下儲存的資料:

>SELECT * FROM justjson; id |               doc----+---------------------------------  1 | {                              +    |     "name":"fred",             +    |     "address":{                +    |         "line1":"52 The Elms", +    |         "line2":"Elmstreet",   +    |         "postcode":"ES1 1ES"   +    |         }                      +    |     }(1 row)

跟儲存之前的文本一模一樣,但我們仍可以解析出具體的資料出來,PostgreSQL提供了一套JSON的操作方法進行尋找,例如,我們只要查出address資訊,如果做?

select doc->>‘address‘ FROM justjson;              ?column?--------------------------------- {                              +         "line1":"52 The Elms", +         "line2":"Elmstreet",   +         "postcode":"ES1 1ES"   +         }(1 row)

doc欄位的 ->> 操作符是查詢JSON對象的某個欄位並返迴文本,用數字也可以當作數組的索引,但仍返迴文本。跟 ->> 類似的還有 -> 操作符,返回不轉文本的內容,可以用它來導航搜尋JSON對象,如:

select doc->‘address‘->>‘postcode‘ FROM justjson;   ?column?---------- ES1 1ES(1 row)

還有個更簡短的寫法來指定搜尋路徑,用 #>> 操作符,如夢:

select doc#>>‘{address,postcode}‘ FROM justjson;   ?column?---------- ES1 1ES(1 row)

通過儲存完整的JSON資料類型可使其跟來源資料完全一樣並且不會丟失內容,但為保持完全一致也帶來了成本,效能的缺失,而且不能索引...所有,儘管可以很方便的維持一致性和保持JSON文檔,但仍有很大的提升空間,所以引入了JSONB。

"JSONB有什麼不同?"

JSONB可以將整個JSON文檔轉有層級的KEY/VALUE資料對,所有的空白字元刪除了,重複鍵只保留最後一次,鍵也沒有排序,而是用HASH來儲存了,上面的例子中用JSONB的版本的話,看來起類似這樣:

>CREATE TABLE justjsonb ( id INTEGER, doc JSONB)>INSERT INTO justjsonb VALUES ( 1, ‘{    "name":"fred",    "address":{        "line1":"52 The Elms",        "line2":"Elmstreet",        "postcode":"ES1 1ES"        }    }‘);>SELECT * FROM justjsonb; id |                                                doc----+----------------------------------------------------------------------------------------------------  1 | {"name": "fred", "address": {"line1": "52 The Elms", "line2": "Elmstreet", "postcode": "ES1 1ES"}}(1 row)

可以看到,所有非常值內容都消失了,替換成JSON文檔需要的最少格式,這種壓縮方式表示當資料插入時會自動格式化,這樣可以減少之後訪問資料分析處理的工作量。

"PostgreSQL的這種資料有點像HSTORE"

看到索引值對,JSONB還真有點像PostgreSQL的HSTORE擴充,它也可以儲存索引值對,但它是一個擴充,而,JSONB(以及JSON)是在PostgreSQL核心的,HSTORE只有一級層級,但PostgreSQL可以有嵌套的元素,並且,HSTORE只能存字串,而JSONB還可以存JSON的所數字類型。

“那JSONB到底帶給我啥好處呢?”

索引,到處用上索引,你不能在PostgreSQL對JSON類型建立真正的索引,你可以建立運算式索引(expression indexes),但只限於你想索引的內容,例如:

create index justjson_postcode on justjson ((doc->‘address‘->>‘postcode‘));

只有郵編(postcode)索引了,其它都沒有索引。

而JSONB,支援GIN索引,一種通用返轉索引(Generalized Inverted Index),PostgreSQL提供了另外一套索引操作符來支援,包括 @> 包括JSON,<@ 最包含,? 測試字串是否存在,?| 任一字元串是否存在,?& 所有存大的字串。

有兩類索引可用,預設叫 json_ops,它支援所有操作符(譯者:指普通json操作符)和一個只支援&>操作符的jsonb_path_ops索引(譯者:指索引操作符),預設索引給JSON中的每個索引值都建立了索引,其實 jsonb_path_ops只建立了一個比預設複雜的更高壓縮的hash表索引,但預設索引擔任更多操作能力同時增加了空間成本。給表添加一些資料,我們再來看看某個郵編,如果我們建立了一個預設的GIN JSON索引然後查詢:

explain select * from justjsonb where doc @> ‘{ "address": { "postcode":"HA36CC" } }‘;                             QUERY PLAN----------------------------------------------------------------- Seq Scan on justjsonb  (cost=0.00..3171.14 rows=100 {"address": {"postcode": "HA36CC"}}‘::jsonb)(2 rows)

可以看出來是順序掃瞄表,如果我們加個預設的JSON GIN索引後再看看有什麼不同?

> create index justjsonb_gin on justjsonb using gin (doc);> explain select * from justjsonb where doc @> ‘{ "address": { "postcode":"HA36CC" } }‘;                                  QUERY PLAN------------------------------------------------------------------------------- Bitmap Heap Scan on justjsonb  (cost=40.78..367.62 rows=100 {"address": {"postcode": "HA36CC"}}‘::jsonb)   ->  Bitmap Index Scan on justjsonb_gin  (cost=0.00..40.75 rows=100 {"address": {"postcode": "HA36CC"}}‘::jsonb)(4 rows)

搜尋效能提升很大,但隱藏了空間的耗費,例中是41%的資料大小,讓我們刪除索引重複執行jsonb_path_ops GIN索引。

> create index justjsonb_gin on justjsonb using gin (doc jsonb_path_ops);> explain select * from justjsonb where doc @> ‘{ "address": { "postcode":"HA36CC" } }‘;                                  QUERY PLAN------------------------------------------------------------------------------- Bitmap Heap Scan on justjsonb  (cost=16.78..343.62 rows=100 {"address": {"postcode": "HA36CC"}}‘::jsonb)   ->  Bitmap Index Scan on justjsonb_gin  (cost=0.00..16.75 rows=100 {"address": {"postcode": "HA36CC"}}‘::jsonb)(4 rows)

總成本低了點,索引體積小了很多,這是典型的建立索引速度和空間平衡的方法,但比順序掃瞄效能高很多。


“我應該用它作為我的JSON資料庫嗎?”

如果你經常更新你的JSON文檔,回答是否定的,PostgreSQL最擅長的是儲存和攻取JSON文檔及他們的欄位,但儘管如此你可以取出單個欄位,你也不能更新單個欄位;實際上你可以,將整個JSON解析出來,添加新的欄位再寫回,讓JSON分析器處理重複,但你很明顯不想依賴這個。

如果你的主要資料用關聯式資料庫用得很好,JSON資料只是一群補充(待用資料),那麼用PostgreSQL就可以了,而且用JSONB表示和索引能力將更高效。另外,如果你的資料模型是可變內容的集合,那麼你可能會尋找一樣主流工業級的json文檔資料庫如MongoDB或RethinkDB。

參考

PostgreSQL vs MongoDB http://my.oschina.net/Suregogo/blog/358277

Query JSON in PostgreSQL http://schinckel.net/2014/05/25/querying-json-in-postgres/

原文: https://www.compose.io/articles/is-postgresql-your-next-json-database/

<譯:朱淦 [email protected]>

PostgreSQL是不是你的下一個JSON資料庫?

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.