2017-02-15 4 views
4

PostgreSQL 용 JSONB를 발견했으며 모든 테이블 열에 사용하면 어떤 문제가 발생할 수 있는지 궁금합니다.기본 키와 외래 키가 아닌 postgres 열에 JSONB 사용

즉, 모든 테이블은 기본 데이터와 외래 키가 열이고 다른 데이터는 field JSONB 유형의 열입니다.

JSONB의 오버 헤드로 인해 추가 공간을 차지하고 "열"에 대한 입력을 잃어 버리는 것 외에 나는 무엇을 놓치겠습니까?

답변

3

여기에 뭔가있는 것으로 나타났습니다.

관계형 데이터베이스 사용의 주요 사항.

  • 잘 정의 된 관계.
  • 잘 정의되고 상세한 스키마.
  • 큰 데이터 세트의 경우 높은 성능.

당신은 관계를 유지하게됩니다. 그러나 스키마와 많은 성능을 잃게됩니다. 스키마는 단순히 데이터 유효성 검사 이상의 것입니다. 즉, 개별 필드에 트리거 또는 제한 조건을 사용할 수 없습니다.

성능 측면에서 보면 JSONB 성능 테스트는 대부분 다른 유사한 데이터 유형에 대한 테스트임을 알 수 있습니다. 그들은 정상적인 SQL 테이블을 절대 반대하지 않습니다. 이는 JSONB가 놀랍도록 효율적이지만 일반 SQL만큼 효율적이지 않기 때문입니다. 그래서 그것을 시험해 봅시다, 당신이 여기에있는 것을 보게됩니다. 나는 적절한 SQL 스키마를 생성 this JSONB performance presentation에서 데이터 집합을 사용

...

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 
); 

그러면 I imported the same data into both sets of tables using a little script입니다. 589859 제품 리뷰, 93319 제품, 98761 고객.

JSONB 성능 도움말에서 제품 카테고리에 대한 평균 리뷰를 얻는 것과 같은 쿼리를 사용해 보겠습니다. 첫째, 색인없이.

전통적인 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 

전체 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 

하이브리드 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 

. 하이브리드 방식은 전체 JSONB보다 두 배 빠르지 만 일반 SQL보다 50 % 느립니다. 인덱스는 어떻습니까?

전통적인 SQL : 130 MS (인덱스 용 +500 MS)

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 MS (인덱스 대 25000 + MS)

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 MS (그것은이 쿼리 색인입니다 밝혀 인덱스에 대한 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 열에 유연성을 위해 추가 필드를 선택하십시오.

여기서 테스트 데이터를 가지고 놀고 성능이 어떤지 확인하십시오.

관련 문제