我剛剛發現了PostgreSQL的JSONB,並想知道如果我將它用於所有表的列,會出現什麼問題?對主鍵和外鍵以外的postgres列使用JSONB
也就是說我所有的表將有主鍵和外鍵列和類型JSONB的任何其他數據的field
列。
除了佔用額外的空間,因爲JSONB的開銷,並失去打字「列」,那會我錯過?
我剛剛發現了PostgreSQL的JSONB,並想知道如果我將它用於所有表的列,會出現什麼問題?對主鍵和外鍵以外的postgres列使用JSONB
也就是說我所有的表將有主鍵和外鍵列和類型JSONB的任何其他數據的field
列。
除了佔用額外的空間,因爲JSONB的開銷,並失去打字「列」,那會我錯過?
事實證明,你在這裏的東西。
使用關係數據庫的要點。
玩家可以不斷的關係。但是你失去了架構和很多的性能。模式不僅僅是數據驗證。這意味着您不能在個別字段上使用觸發器或約束條件。
至於性能...你會注意到的JSONB性能最測試是對其他類似的數據類型。他們從不反對正常的SQL表。這是因爲,儘管JSONB效率驚人,但其效率幾乎不如常規SQL高。所以我們來測試一下,結果發現你在這裏做些什麼。
運用this JSONB performance presentation我創建了一個正確的SQL架構中的數據集...
create table customers (
id text primary key
);
create table products (
id text primary key,
title text,
sales_rank integer,
"group" text,
category text,
subcategory text,
similar_ids text[]
);
create table reviews (
customer_id text references customers(id),
product_id text references products(id),
"date" timestamp,
rating integer,
votes integer,
helpful_votes integer
);
,另一種使用SQL的關係,但JSONB數據...
create table customers (
id text primary key
);
create table products_jb (
id text primary key,
fields jsonb
);
create table reviews_jb (
customer_id text references customers(id),
product_id text references products_jb(id),
fields jsonb
);
和一個JSONB表。
create table reviews_jsonb (
review jsonb
);
然後我imported the same data into both sets of tables using a little script。 589859評論,93319產品,98761客戶。
讓我們嘗試相同的查詢作爲JSONB性能的文章,得到的平均評價一個產品類別。首先,沒有索引。
傳統SQL:138毫秒
test=> select round(avg(r.rating), 2)
from reviews r
join products p on p.id = r.product_id
where p.category = 'Home & Garden';
round
-------
4.59
(1 row)
Time: 138.631 ms
完全JSONB:380毫秒
test=> select round(avg((review#>>'{review,rating}')::numeric),2)
test-> from reviews_jsonb
test-> where review #>>'{product,category}' = 'Home & Garden';
round
-------
4.59
(1 row)
Time: 380.697 ms
混合JSONB:190毫秒
test=> select round(avg((r.fields#>>'{rating}')::numeric),2)
from reviews_jb r
join products_jb p on p.id = r.product_id
where p.fields#>>'{category}' = 'Home & Garden';
round
-------
4.59
(1 row)
Time: 192.333 ms
那老老實實去比想象的要好。混合方法的速度是完整JSONB的兩倍,但比普通SQL慢50%。現在如何與索引?
傳統SQL:130毫秒(500毫秒的索引)
test=> create index products_category on products(category);
CREATE INDEX
Time: 491.969 ms
test=> select round(avg(r.rating), 2)
from reviews r
join products p on p.id = r.product_id
where p.category = 'Home & Garden';
round
-------
4.59
(1 row)
Time: 128.212 ms
全JSONB:360毫秒(+ 25000毫秒的索引)
test=> create index on reviews_jsonb using gin(review);
CREATE INDEX
Time: 25253.348 ms
test=> select round(avg((review#>>'{review,rating}')::numeric),2)
from reviews_jsonb
where review #>>'{product,category}' = 'Home & Garden';
round
-------
4.59
(1 row)
Time: 363.222 ms
混合JSONB:185毫秒( +6900毫秒爲指標)
test=> create index on products_jb using gin(fields);
CREATE INDEX
Time: 3654.894 ms
test=> create index on reviews_jb using gin(fields);
CREATE INDEX
Time: 3237.534 ms
test=> select round(avg((r.fields#>>'{rating}')::numeric),2)
from reviews_jb r
join products_jb p on p.id = r.product_id
where p.fields#>>'{category}' = 'Home & Garden';
round
-------
4.59
(1 row)
Time: 183.679 ms
原來,這是一個查詢索引不會有太大的幫助。
這就是我所看到的數據有點混雜,混合JSONB總是比完整SQL慢,但比完整JSONB更快。這似乎是一個很好的妥協。您可以使用傳統的外鍵和連接,但可以靈活地添加您喜歡的任何字段。
我建議採取混合方式更進一步:爲您所知的字段使用SQL列,並有一個JSONB列來提取任何其他字段以提高靈活性。
我鼓勵你在這裏玩弄測試數據,看看錶現如何。