2017-02-15 17 views
4

Я только что открыл JSONB для PostgreSQL и задавался вопросом, что может пойти не так, если я использовал его для всех столбцов моих таблиц?Используйте JSONB для столбцов postgres, отличных от первичных и внешних ключей

То есть все мои таблицы имели бы первичные и внешние ключи в виде столбцов и столбец field типа JSONB для любых других данных.

Кроме того, что вы занимаете дополнительное пространство из-за накладных расходов JSONB и теряете печатать на «столбцах», что бы я пропустил?

ответ

3

Получается, что вы здесь.

Основные моменты использования реляционной базы данных.

  • Хорошо определенные отношения.
  • Хорошо определенная и подробная схема.
  • Высокая производительность для больших наборов данных.

Вы должны поддерживать отношения. Но вы теряете схему и много производительности. Схема - это не просто проверка данных. Это означает, что вы не можете использовать триггеры или ограничения для отдельных полей.

Что касается производительности ... вы заметите, что большинство тестов производительности 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 
); 

Then I 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 

Hybrid 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, но на 50% медленнее обычного SQL. Теперь как насчет индексов?

Традиционный 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, но быстрее, чем Full JSONB. Это похоже на хороший компромисс. Вы можете использовать традиционные внешние ключи и объединения, но имеете гибкость добавления любых полей, которые вам нравятся.

Я рекомендую использовать гибридный подход еще на шаг: используйте столбцы SQL для полей, которые, как вы знаете, будут там, и должны иметь столбец JSONB для получения любых дополнительных полей для гибкости.

Я рекомендую вам поиграть с тестовыми данными здесь и посмотреть, что такое производительность.

 Смежные вопросы

  • Нет связанных вопросов^_^