Postgres 9.5를 사용하면 성능을 극대화하기 위해 GIN 인덱스를 결정적으로 활용하여 두 개의 JSON 필드를 조인하여 JSONB 열이있는 테이블을 어떻게 쿼리 할 수 있습니까?Postgres JSONB - 두 개의 JSON 필드 간 조인
단일 플랫폼에서 다른 고객을 위해 서로 다른 스키마/데이터 모델을 수용 할 수있는 시스템을 프로토 타이핑하고 있습니다. Entity-Attribute-Value (EAV)는 이에 대한 일반적인 패턴이며 Postgres가 JSONB 데이터 유형을 사용하여 저장된 엔티티에 대한 쿼리를 얼마나 잘 처리 할 수 있는지 벤치마킹하기를 열망하고 있습니다.
다른 유형의 엔티티를 저장하는 단일 테이블을 보유하고 있습니다. 고객, 판매 거래.
:{"uuid": "8f8896c7-f41c-49f7-ad6e-4613f7b51a23", "email": "[email protected]", "lastname": "McCarthy", "createdAt": "May 27, 2015 12:06:45 PM", "firstname": "Nathan"}
I 형 'sales_transaction'와 속성이 테이블에 판매 거래 기록을 가지고 :
CREATE TABLE entity_jsonb (
id uuid PRIMARY KEY,
type text,
created_at timestamp without time zone,
properties jsonb,
org_id integer
);
CREATE INDEX entity_jsonb_created_at_idx ON entity_jsonb USING btree (created_at);
CREATE INDEX entity_jsonb_org_id_idx ON entity_jsonb USING btree (org_id);
CREATE INDEX entity_jsonb_type_idx ON entity_jsonb USING btree (type);
CREATE INDEX entity_jsonb_properties_idx ON entity_jsonb USING gin (properties);
나는 형 '고객'과 속성이 테이블에 고객 기록이
{"uuid": "54243d48-e69f-4bb6-ab33-6defb8a0f626", "amount": 99817, "status": 0, "paymentType": 1, "currencyCode": "USD", "customerUuid": "8f8896c7-f41c-49f7-ad6e-4613f7b51a23", "transactionId": "471170"}
GIN 인덱스 (연산자 : @>,?,? &,? |)를 사용하면 트랜잭션을 효율적으로 쿼리 할 수 있지만 고객과 합류하면 데이터를 반환 할 수 있습니다. 둘 다. 지난 7 일간의 거래 목록을 채우고 고객 이름과 거래 금액을 표시 하시겠습니까?
나는 및 관련 고객의 세부 사항 (양 = 99817에 대한) 트랜잭션 객체의 하위 집합 찾기 위해이 쿼리를 시도했다 :
SELECT t.properties AS transaction, c.properties AS customer
FROM entity_jsonb t
JOIN entity_jsonb c ON (c.properties->>'uuid' = t.properties->>'customerUuid' AND c.type = 'customer')
WHERE t.type = 'sales_transaction' AND t.properties @> '{"amount" : 99817}';
그것은 작동을하지만 나는만큼 빨리 GIN 인덱스 즉,하지를 사용하지 않는 것 그것을 좋아한다. 나는 GIN @> containment 연산자를 사용하여이 접근법을 시도했지만 고객 세부 정보는 포함하지 않았다. 내가 도대체 뭘 잘못하고있는 겁니까?
SELECT t.properties AS transaction, c.properties AS customer FROM entity_jsonb t LEFT JOIN entity_jsonb c ON (c.properties @> json_build_array(json_build_object('uuid', t.properties->'customerUuid'))::jsonb AND c.type = 'customer') WHERE t.type = 'sales_transaction' AND t.properties @> '{"amount" : 99817}';
나는이 전통적인 관계형 디자인과 비교하여 최적의 솔루션이 아닙니다하지만 난 쿼리가 JSON과 같은 엔티티 데이터를 저장하는 순수 할 수있는 방법을 효율적으로보고 관심이 있음을 이해합니다.