Es stellt sich heraus, Sie sind hier auf etwas.
Die wichtigsten Punkte der Verwendung einer relationalen Datenbank.
- Gut definierte Beziehungen.
- Ein gut definiertes und detailliertes Schema.
- Hohe Leistung für große Datenmengen.
Sie erhalten die Beziehungen zu halten. Aber Sie verlieren das Schema und viel Leistung. Das Schema ist mehr als nur eine Datenvalidierung. Dies bedeutet, dass Sie keine Trigger oder Einschränkungen für einzelne Felder verwenden können.
In Bezug auf die Leistung ... werden Sie feststellen, dass die meisten Tests der JSONB-Leistung gegen andere ähnliche Datentypen sind. Sie sind nie gegen normale SQL-Tabellen. JSONB ist zwar erstaunlich effizient, aber nicht so effizient wie normales SQL. Lass es uns testen, es stellt sich heraus, dass du hier etwas hast.
Verwenden den Datensatz aus this JSONB performance presentation ich ein richtigen SQL-Schema erstellt ...
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
);
Und eine, die für die Daten SQL Beziehungen aber JSONB verwendet ...
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
);
Und ein einziger JSONB Tisch .
create table reviews_jsonb (
review jsonb
);
Dann ich imported the same data into both sets of tables using a little script. 589859 Bewertungen, 93319 Produkte, 98761 Kunden.
Lassen Sie uns die gleiche Abfrage wie im JSONB-Performance-Artikel verwenden, um die durchschnittliche Bewertung für eine Produktkategorie zu erhalten. Erstens, ohne Indizes.
Traditionelle SQL: 138 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: 138.631 ms
Voll JSONB: 380 ms
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
Hybrid JSONB: 190 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: 192.333 ms
die ehrlich besser ging, als es dachte. Der Hybrid-Ansatz ist doppelt so schnell wie voller JSONB, aber 50% langsamer als normaler SQL. Wie wäre es mit Indizes?
Traditionelle SQL: 130 ms (500 ms für den Index)
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
Voll JSONB: 360 ms (+ 25000 ms für den Index)
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
Hybrid JSONB: 185 ms (6900 ms für die Indizes)
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
Es stellt sich heraus, das ist eine Abfrage Indizierung wird nicht viel Hilfe sein.
Das ist, was ich mit den Daten ein wenig zu spielen, Hybrid JSONB ist immer langsamer als Full SQL, aber schneller als Full JSONB. Es scheint ein guter Kompromiss zu sein. Sie können traditionelle Fremdschlüssel und Joins verwenden, haben aber die Flexibilität, beliebige Felder hinzuzufügen.
Ich empfehle den hybriden Ansatz einen Schritt weiter zu gehen: Verwenden Sie SQL-Spalten für die Felder, von denen Sie wissen, dass sie da sein werden, und eine JSONB-Spalte, um zusätzliche Felder für Flexibilität aufzunehmen.
Ich ermutige Sie, hier mit den Testdaten herumzuspielen und zu sehen, wie die Leistung ist.