ื”ื—ืœืคืช EAV ื‘-JSONB ื‘-PostgreSQL

TL; DR: JSONB ื™ื›ื•ืœ ืœืคืฉื˜ ืžืื•ื“ ืืช ืคื™ืชื•ื— ืกื›ื™ืžืช ืžืกื“ ื ืชื•ื ื™ื ืžื‘ืœื™ ืœื”ืงืจื™ื‘ ืืช ื‘ื™ืฆื•ืขื™ ื”ืฉืื™ืœืชื•ืช.

ืžื‘ื•ื

ื‘ื•ื ื ื™ืชืŸ ื“ื•ื’ืžื” ืงืœืืกื™ืช ืœืื—ื“ ืžืžืงืจื™ ื”ืฉื™ืžื•ืฉ ื”ืขืชื™ืงื™ื ื‘ื™ื•ืชืจ ื‘ืขื•ืœื ืฉืœ ืžืกื“ ื ืชื•ื ื™ื ื™ื—ืกื™ (ื‘ืกื™ืก ื ืชื•ื ื™ื): ื™ืฉ ืœื ื• ื™ืฉื•ืช, ื•ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœืฉืžื•ืจ ืžืืคื™ื™ื ื™ื ืžืกื•ื™ืžื™ื (ืžืืคื™ื™ื ื™ื) ืฉืœ ื”ื™ืฉื•ืช ื”ื–ื•. ืืš ื™ื™ืชื›ืŸ ืฉืœื ืœื›ืœ ื”ืžื•ืคืขื™ื ื™ืฉ ืืช ืื•ืชื” ืงื‘ื•ืฆืช ืžืืคื™ื™ื ื™ื, ื•ื™ื™ืชื›ืŸ ืฉื™ืชื•ื•ืกืคื• ืžืืคื™ื™ื ื™ื ื ื•ืกืคื™ื ื‘ืขืชื™ื“.

ื”ื“ืจืš ื”ืงืœื” ื‘ื™ื•ืชืจ ืœืคืชื•ืจ ื‘ืขื™ื” ื–ื• ื”ื™ื ืœื™ืฆื•ืจ ืขืžื•ื“ื” ื‘ื˜ื‘ืœืช ืžืกื“ ื”ื ืชื•ื ื™ื ืขื‘ื•ืจ ื›ืœ ืขืจืš ืžืืคื™ื™ืŸ, ื•ืคืฉื•ื˜ ืœืžืœื ืืช ืืœื” ื”ื“ืจื•ืฉื™ื ืขื‘ื•ืจ ืžื•ืคืข ื™ืฉื•ืช ืกืคืฆื™ืคื™. ื’ื“ื•ืœ! ื”ื‘ืขื™ื” ื ืคืชืจื”... ืขื“ ืฉื”ื˜ื‘ืœื” ืฉืœืš ืชื›ื™ืœ ืžื™ืœื™ื•ื ื™ ืจืฉื•ืžื•ืช ื•ืืชื” ืฆืจื™ืš ืœื”ื•ืกื™ืฃ ืจืฉื•ืžื” ื—ื“ืฉื”.

ืฉืงื•ืœ ืืช ื“ืคื•ืก ื”-EAV (ืขืจืš-ืชื›ื•ื ื”-ื™ืฉื•ืช), ื–ื” ืžืชืจื—ืฉ ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืœืžื“ื™. ื˜ื‘ืœื” ืื—ืช ืžื›ื™ืœื” ื™ืฉื•ื™ื•ืช (ืจืฉื•ืžื•ืช), ื˜ื‘ืœื” ืื—ืจืช ืžื›ื™ืœื” ืฉืžื•ืช ืžืืคื™ื™ื ื™ื (ืžืืคื™ื™ื ื™ื), ื•ื˜ื‘ืœื” ืฉืœื™ืฉื™ืช ืžืฉื™ื™ื›ืช ื™ืฉื•ื™ื•ืช ืœืชื›ื•ื ื•ืช ืฉืœื”ืŸ ื•ืžื›ื™ืœื” ืืช ื”ืขืจืš ืฉืœ ื”ืชื›ื•ื ื•ืช ื”ืœืœื• ืขื‘ื•ืจ ื”ื™ืฉื•ืช ื”ื ื•ื›ื—ื™ืช. ื–ื” ื ื•ืชืŸ ืœืš ืืช ื”ื™ื›ื•ืœืช ืœืงื‘ืœ ืงื‘ื•ืฆื•ืช ืฉื•ื ื•ืช ืฉืœ ืžืืคื™ื™ื ื™ื ืขื‘ื•ืจ ืื•ื‘ื™ื™ืงื˜ื™ื ืฉื•ื ื™ื, ื•ื’ื ืœื”ื•ืกื™ืฃ ืžืืคื™ื™ื ื™ื ืชื•ืš ื›ื“ื™ ืžื‘ืœื™ ืœืฉื ื•ืช ืืช ืžื‘ื ื” ืžืกื“ ื”ื ืชื•ื ื™ื.

ืขื ื–ืืช, ืœื ื”ื™ื™ืชื™ ื›ื•ืชื‘ ืืช ื”ืคื•ืกื˜ ื”ื–ื” ืื ืœื ื”ื™ื• ื›ืžื” ื—ืกืจื•ื ื•ืช ืœื’ื™ืฉืช EVA. ื›ืš, ืœืžืฉืœ, ื›ื“ื™ ืœื”ืฉื™ื’ ื™ืฉื•ืช ืื—ืช ืื• ื™ื•ืชืจ ืฉื™ืฉ ืœื”ืŸ ืชื›ื•ื ื” ืื—ืช ืœื›ืœ ืื—ืช, ื ื“ืจืฉื•ืช 1 ื”ืฆื˜ืจืคื•ืช ื‘ืฉืื™ืœืชื”: ื”ืจืืฉื•ื ื” ื”ื™ื ืฆื™ืจื•ืฃ ืขื ื˜ื‘ืœืช ื”ืชื›ื•ื ื•ืช, ื”ืฉื ื™ื™ื” ื”ื™ื ืฆื™ืจื•ืฃ ืขื ื˜ื‘ืœืช ื”ืขืจื›ื™ื. ืื ืœื™ืฉื•ืช ื™ืฉ 2 ืชื›ื•ื ื•ืช, ื™ืฉ ืฆื•ืจืš ื‘-2 ื”ืฆื˜ืจืคื•ืช! ื‘ื ื•ืกืฃ, ื›ืœ ื”ืชื›ื•ื ื•ืช ืžืื•ื—ืกื ื•ืช ื‘ื“ืจืš ื›ืœืœ ื›ืžื—ืจื•ื–ื•ืช, ืžื” ืฉื’ื•ืจื ืœื”ื˜ืœืช ืกื•ื’ ื”ืŸ ืขื‘ื•ืจ ื”ืชื•ืฆืื” ื•ื”ืŸ ืขื‘ื•ืจ ืกืขื™ืฃ WHERE. ืื ืืชื” ื›ื•ืชื‘ ื”ืจื‘ื” ืฉืื™ืœืชื•ืช, ืื– ื–ื” ื“ื™ ื‘ื–ื‘ื–ื ื™ ืžื‘ื—ื™ื ืช ืฉื™ืžื•ืฉ ื‘ืžืฉืื‘ื™ื.

ืœืžืจื•ืช ื”ื—ืกืจื•ื ื•ืช ื”ื‘ืจื•ืจื™ื ื”ืœืœื•, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘-EAV ื›ื‘ืจ ื–ืžืŸ ืจื‘ ื›ื“ื™ ืœืคืชื•ืจ ื‘ืขื™ื•ืช ืžืกื•ื’ ื–ื”. ืืœื• ื”ื™ื• ื—ืกืจื•ื ื•ืช ื‘ืœืชื™ ื ืžื ืขื™ื, ื•ืคืฉื•ื˜ ืœื ื”ื™ื™ืชื” ืืœื˜ืจื ื˜ื™ื‘ื” ื˜ื•ื‘ื” ื™ื•ืชืจ.
ืื‘ืœ ืื– ื”ื•ืคื™ืขื” "ื˜ื›ื ื•ืœื•ื’ื™ื”" ื—ื“ืฉื” ื‘-PostgreSQL...

ื”ื—ืœ ืž-PostgreSQL 9.4, ืกื•ื’ ื”ื ืชื•ื ื™ื JSONB ื ื•ืกืฃ ืœืื—ืกื•ืŸ ื ืชื•ื ื™ื ื‘ื™ื ืืจื™ื™ื ืฉืœ JSON. ืœืžืจื•ืช ืฉืื—ืกื•ืŸ JSON ื‘ืคื•ืจืžื˜ ื–ื” ืœื•ืงื— ื‘ื“ืจืš ื›ืœืœ ืงืฆืช ื™ื•ืชืจ ืžืงื•ื ื•ื–ืžืŸ ืžืืฉืจ JSON ื‘ื˜ืงืกื˜ ืจื’ื™ืœ, ื‘ื™ืฆื•ืข ื”ืคืขื•ืœื•ืช ื‘ื• ื”ื•ื ื”ืจื‘ื” ื™ื•ืชืจ ืžื”ื™ืจ. JSONB ืชื•ืžืš ื’ื ื‘ืื™ื ื“ืงืก, ืžื” ืฉื”ื•ืคืš ืืช ื”ืฉืื™ืœืชื•ืช ืœืžื”ื™ืจ ืขื•ื“ ื™ื•ืชืจ.

ืกื•ื’ ื”ื ืชื•ื ื™ื JSONB ืžืืคืฉืจ ืœื ื• ืœื”ื—ืœื™ืฃ ืืช ืชื‘ื ื™ืช ื”-EAV ื”ืžืกื•ืจื‘ืœืช ืขืœ ื™ื“ื™ ื”ื•ืกืคืช ืขืžื•ื“ืช JSONB ืื—ืช ื‘ืœื‘ื“ ืœื˜ื‘ืœืช ื”ื™ืฉื•ื™ื•ืช ืฉืœื ื•, ืžื” ืฉืžืคืฉื˜ ืžืื•ื“ ืืช ืขื™ืฆื•ื‘ ืžืกื“ ื”ื ืชื•ื ื™ื. ืื‘ืœ ืจื‘ื™ื ื˜ื•ืขื ื™ื ืฉื–ื” ืฆืจื™ืš ืœื”ื™ื•ืช ืžืœื•ื•ื” ื‘ื™ืจื™ื“ื” ื‘ืคืจื™ื•ืŸ... ืœื›ืŸ ื›ืชื‘ืชื™ ืืช ื”ืžืืžืจ ื”ื–ื”.

ื”ืงืžืช ืžืกื“ ื ืชื•ื ื™ื ืœื‘ื“ื™ืงื•ืช

ืœืฆื•ืจืš ื”ืฉื•ื•ืื” ื–ื•, ื™ืฆืจืชื™ ืืช ืžืกื“ ื”ื ืชื•ื ื™ื ืขืœ ื”ืชืงื ื” ื—ื“ืฉื” ืฉืœ PostgreSQL 9.5 ื‘-build $80 DigitalOcean ืื•ื‘ื•ื ื˜ื• 14.04. ืœืื—ืจ ื”ื’ื“ืจืช ื›ืžื” ืคืจืžื˜ืจื™ื ื‘-postgresql.conf ืจืฆืชื™ ื–ื” ืกืงืจื™ืคื˜ ื‘ืืžืฆืขื•ืช psql. ื”ื˜ื‘ืœืื•ืช ื”ื‘ืื•ืช ื ื•ืฆืจื• ื›ื“ื™ ืœื”ืฆื™ื’ ืืช ื”ื ืชื•ื ื™ื ื‘ืฆื•ืจืช EAV:

CREATE TABLE entity ( 
  id           SERIAL PRIMARY KEY, 
  name         TEXT, 
  description  TEXT
);
CREATE TABLE entity_attribute (
  id          SERIAL PRIMARY KEY, 
  name        TEXT
);
CREATE TABLE entity_attribute_value (
  id                  SERIAL PRIMARY KEY, 
  entity_id           INT    REFERENCES entity(id), 
  entity_attribute_id INT    REFERENCES entity_attribute(id), 
  value               TEXT
);

ืœื”ืœืŸ ื˜ื‘ืœื” ืฉื‘ื” ื™ื™ืฉืžืจื• ืื•ืชื ื ืชื•ื ื™ื, ืืš ืขื ืชื›ื•ื ื•ืช ื‘ืขืžื•ื“ืช ืกื•ื’ JSONB - ื ื›ืกื™ื.

CREATE TABLE entity_jsonb (
  id          SERIAL PRIMARY KEY, 
  name        TEXT, 
  description TEXT,
  properties  JSONB
);

ื ืจืื” ื”ืจื‘ื” ื™ื•ืชืจ ืคืฉื•ื˜, ืœื? ืœืื—ืจ ืžื›ืŸ ื”ื•ื ื”ืชื•ื•ืกืฃ ืœื˜ื‘ืœืื•ืช ื”ื™ืฉื•ื™ื•ืช (ื™ืฉื•ืช & entity_jsonb) 10 ืžื™ืœื™ื•ืŸ ืจืฉื•ืžื•ืช, ื•ื‘ื”ืชืื ืœื›ืš, ื”ื˜ื‘ืœื” ื”ืชืžืœืื” ื‘ืื•ืชื ื ืชื•ื ื™ื ื‘ืืžืฆืขื•ืช ื“ืคื•ืก ื”-EAV ื•ื”ื’ื™ืฉื” ืขื ืขืžื•ื“ืช JSONB - entity_jsonb.properties. ืœืคื™ื›ืš, ืงื™ื‘ืœื ื• ืžืกืคืจ ืกื•ื’ื™ ื ืชื•ื ื™ื ืฉื•ื ื™ื ื‘ื™ืŸ ื›ืœ ืžืขืจืš ื”ืžืืคื™ื™ื ื™ื. ื ืชื•ื ื™ื ืœื“ื•ื’ืžื”:

{
  id:          1
  name:        "Entity1"
  description: "Test entity no. 1"
  properties:  {
    color:        "red"
    lenght:       120
    width:        3.1882420
    hassomething: true
    country:      "Belgium"
  } 
}

ืื– ืขื›ืฉื™ื• ื™ืฉ ืœื ื• ืืช ืื•ืชื ื ืชื•ื ื™ื ืขื‘ื•ืจ ืฉืชื™ ื”ืืคืฉืจื•ื™ื•ืช. ื‘ื•ืื• ื ืชื—ื™ืœ ืœื”ืฉื•ื•ืช ื™ื™ืฉื•ืžื™ื ื‘ืขื‘ื•ื“ื”!

ืคืฉื˜ ืืช ื”ืขื™ืฆื•ื‘ ืฉืœืš

ื ืืžืจ ื‘ืขื‘ืจ ื›ื™ ืขื™ืฆื•ื‘ ืžืกื“ ื”ื ืชื•ื ื™ื ื”ื™ื” ืžืคื•ืฉื˜ ืžืื•ื“: ื˜ื‘ืœื” ืื—ืช, ืขืœ ื™ื“ื™ ืฉื™ืžื•ืฉ ื‘ืขืžื•ื“ืช JSONB ืœืžืืคื™ื™ื ื™ื, ื‘ืžืงื•ื ืฉื™ืžื•ืฉ ื‘ืฉืœื•ืฉ ื˜ื‘ืœืื•ืช ืขื‘ื•ืจ EAV. ืื‘ืœ ืื™ืš ื–ื” ื‘ื ืœื™ื“ื™ ื‘ื™ื˜ื•ื™ ื‘ื‘ืงืฉื•ืช? ืขื“ื›ื•ืŸ ืžืืคื™ื™ืŸ ื™ืฉื•ืช ืื—ื“ ื ืจืื” ื›ืš:

-- EAV
UPDATE entity_attribute_value 
SET value = 'blue' 
WHERE entity_attribute_id = 1 
  AND entity_id = 120;

-- JSONB
UPDATE entity_jsonb 
SET properties = jsonb_set(properties, '{"color"}', '"blue"') 
WHERE id = 120;

ื›ืคื™ ืฉืืชื” ื™ื›ื•ืœ ืœืจืื•ืช, ื”ื‘ืงืฉื” ื”ืื—ืจื•ื ื” ืœื ื ืจืื™ืช ืคืฉื•ื˜ื” ื™ื•ืชืจ. ื›ื“ื™ ืœืขื“ื›ืŸ ืืช ื”ืขืจืš ืฉืœ ืžืืคื™ื™ืŸ ื‘ืื•ื‘ื™ื™ืงื˜ JSONB ืขืœื™ื ื• ืœื”ืฉืชืžืฉ ื‘ืคื•ื ืงืฆื™ื” jsonb_set(), ื•ืืžื•ืจ ืœื”ืขื‘ื™ืจ ืืช ื”ืขืจืš ื”ื—ื“ืฉ ืฉืœื ื• ื›ืื•ื‘ื™ื™ืงื˜ JSONB. ืขื ื–ืืช, ืื ื—ื ื• ืœื ืฆืจื™ื›ื™ื ืœื“ืขืช ืฉื•ื ืžื–ื”ื” ืžืจืืฉ. ื‘ื”ืกืชื›ืœื•ืช ืขืœ ื“ื•ื’ืžื” EAV, ืขืœื™ื ื• ืœื“ืขืช ื’ื ืืช ื”-entity_id ื•ื’ื ืืช entity_attribute_id ื›ื“ื™ ืœื‘ืฆืข ืืช ื”ืขื“ื›ื•ืŸ. ืื ืืชื” ืจื•ืฆื” ืœืขื“ื›ืŸ ืžืืคื™ื™ืŸ ื‘ืขืžื•ื“ืช JSONB ืขืœ ืกืžืš ืฉื ื”ืื•ื‘ื™ื™ืงื˜, ืื– ื”ื›ืœ ื ืขืฉื” ื‘ืฉื•ืจื” ืื—ืช ืคืฉื•ื˜ื”.

ื›ืขืช, ื‘ื•ืื• ื ื‘ื—ืจ ืืช ื”ื™ืฉื•ืช ืฉืขื“ื›ื ื• ื–ื” ืขืชื” ืขืœ ืกืžืš ื”ืฆื‘ืข ื”ื—ื“ืฉ ืฉืœื”:

-- EAV
SELECT e.name 
FROM entity e 
  INNER JOIN entity_attribute_value eav ON e.id = eav.entity_id
  INNER JOIN entity_attribute ea ON eav.entity_attribute_id = ea.id
WHERE ea.name = 'color' AND eav.value = 'blue';

-- JSONB
SELECT name 
FROM entity_jsonb 
WHERE properties ->> 'color' = 'blue';

ืื ื™ ื—ื•ืฉื‘ ืฉืื ื—ื ื• ื™ื›ื•ืœื™ื ืœื”ืกื›ื™ื ืฉื”ืฉื ื™ ืงืฆืจ ื™ื•ืชืจ (ืื™ืŸ ื”ืฆื˜ืจืคื•ืช!), ื•ืœื›ืŸ ืงืจื™ื ื™ื•ืชืจ. JSONB ืžื ืฆื— ื›ืืŸ! ืื ื• ืžืฉืชืžืฉื™ื ื‘ืื•ืคืจื˜ื•ืจ JSON ->> ื›ื“ื™ ืœืงื‘ืœ ืืช ื”ืฆื‘ืข ื›ืขืจืš ื˜ืงืกื˜ ืžืื•ื‘ื™ื™ืงื˜ JSONB. ื™ืฉื ื” ื’ื ื“ืจืš ืฉื ื™ื™ื” ืœื”ืฉื™ื’ ืืช ืื•ืชื” ืชื•ืฆืื” ื‘ืžื•ื“ืœ JSONB ื‘ืืžืฆืขื•ืช ื”ืื•ืคืจื˜ื•ืจ @>:

-- JSONB 
SELECT name 
FROM entity_jsonb 
WHERE properties @> '{"color": "blue"}';

ื–ื” ืงืฆืช ื™ื•ืชืจ ืžืกื•ื‘ืš: ืื ื—ื ื• ื‘ื•ื“ืงื™ื ืื ืื•ื‘ื™ื™ืงื˜ JSON ื‘ืขืžื•ื“ืช ื”ืžืืคื™ื™ื ื™ื ืฉืœื• ืžื›ื™ืœ ืื•ื‘ื™ื™ืงื˜ ืฉื ืžืฆื ืžื™ืžื™ืŸ ืœืื•ืคืจื˜ื•ืจ @>. ืคื—ื•ืช ืงืจื™ื, ืคืจื•ื“ื•ืงื˜ื™ื‘ื™ ื™ื•ืชืจ (ืจืื” ืœื”ืœืŸ).

ื‘ื•ืื• ื ื”ืคื•ืš ืืช ื”ืฉื™ืžื•ืฉ ื‘-JSONB ืœืงืœ ืขื•ื“ ื™ื•ืชืจ ื›ืืฉืจ ืขืœื™ื›ื ืœื‘ื—ื•ืจ ืžืกืคืจ ืžืืคื™ื™ื ื™ื ื‘ื•-ื–ืžื ื™ืช. ื›ืืŸ ื‘ืืžืช ื ื›ื ืกืช ืœืชืžื•ื ื” ื’ื™ืฉืช JSONB: ืื ื• ืคืฉื•ื˜ ื‘ื•ื—ืจื™ื ืžืืคื™ื™ื ื™ื ื›ืขืžื•ื“ื•ืช ื ื•ืกืคื•ืช ื‘ืขืจื›ืช ื”ืชื•ืฆืื•ืช ืฉืœื ื• ืœืœื ืฆื•ืจืš ื‘ื”ืฆื˜ืจืคื•ืช:

-- JSONB 
SELECT name
  , properties ->> 'color'
  , properties ->> 'country'
FROM entity_jsonb 
WHERE id = 120;

ืขื EAV ืชืฆื˜ืจืš 2 ื”ืฆื˜ืจืคื•ืช ืœื›ืœ ื ื›ืก ืฉืืชื” ืจื•ืฆื” ืœืฉืื•ืœ. ืœื“ืขืชื™, ื”ืฉืื™ืœืชื•ืช ืœืขื™ืœ ืžืจืื•ืช ืคืฉื˜ื•ืช ืจื‘ื” ื‘ืขื™ืฆื•ื‘ ืžืกื“ ื”ื ืชื•ื ื™ื. ืจืื” ื“ื•ื’ืžืื•ืช ื ื•ืกืคื•ืช ื›ื™ืฆื“ ืœื›ืชื•ื‘ ืฉืื™ืœืชื•ืช JSONB, ื’ื ื‘ ื–ื” ื”ื•ื“ืขื”.
ืขื›ืฉื™ื• ื”ื’ื™ืข ื”ื–ืžืŸ ืœื“ื‘ืจ ืขืœ ื‘ื™ืฆื•ืขื™ื.

ืคืจื•ื“ื•ืงื˜ื™ื‘ื™ื•ืช

ื›ื“ื™ ืœื”ืฉื•ื•ืช ื‘ื™ืฆื•ืขื™ื ื”ืฉืชืžืฉืชื™ ื”ืกื‘ืจ ื ื™ืชื•ื— ื‘ืฉืื™ืœืชื•ืช, ืœื—ื™ืฉื•ื‘ ื–ืžืŸ ื‘ื™ืฆื•ืข. ื›ืœ ืฉืื™ืœืชื” ื‘ื•ืฆืขื” ืœืคื—ื•ืช ืฉืœื•ืฉ ืคืขืžื™ื ืžื›ื™ื•ื•ืŸ ืฉืœืžืชื›ื ืŸ ื”ืฉืื™ืœืชื•ืช ืœื•ืงื— ื–ืžืŸ ืจื‘ ื™ื•ืชืจ ื‘ืคืขื ื”ืจืืฉื•ื ื”. ืจืืฉื™ืช ื”ืจืฆืชื™ ืืช ื”ืฉืื™ืœืชื•ืช ืœืœื ื›ืœ ืื™ื ื“ืงืกื™ื. ื‘ืจื•ืจ ืฉื–ื” ื”ื™ื” ื™ืชืจื•ืŸ ืฉืœ JSONB, ืžื›ื™ื•ื•ืŸ ืฉื”ืฆื™ืจื•ืคื™ื ื”ื ื“ืจืฉื™ื ืœ-EAV ืœื ื™ื›ืœื• ืœื”ืฉืชืžืฉ ื‘ืื™ื ื“ืงืกื™ื (ืฉื“ื•ืช ืžืคืชื— ื–ืจื™ื ืœื ื ื•ืกืคื• ืœืื™ื ื“ืงืก). ืœืื—ืจ ืžื›ืŸ ื™ืฆืจืชื™ ืื™ื ื“ืงืก ืขืœ 2 ืขืžื•ื“ื•ืช ื”ืžืคืชื— ื”ื–ืจ ืฉืœ ื˜ื‘ืœืช ื”ืขืจืš EAV, ื•ื›ืŸ ืื™ื ื“ืงืก ื’'ื™ืŸ ืขื‘ื•ืจ ืขืžื•ื“ืช JSONB.

ืขื“ื›ื•ืŸ ื”ื ืชื•ื ื™ื ื”ืจืื” ืืช ื”ืชื•ืฆืื•ืช ื”ื‘ืื•ืช ื‘ืžื•ื ื—ื™ื ืฉืœ ื–ืžืŸ (ื‘-ms). ืฉื™ืžื• ืœื‘ ืฉื”ืกืงืืœื” ื”ื™ื ืœื•ื’ืจื™ืชืžื™ืช:

ื”ื—ืœืคืช EAV ื‘-JSONB ื‘-PostgreSQL

ืื ื• ืจื•ืื™ื ืฉ-JSONB ืžื”ื™ืจ ื‘ื”ืจื‘ื” (>50000-x) ืž-EAV ืื ืื™ื ืš ืžืฉืชืžืฉ ื‘ืื™ื ื“ืงืกื™ื, ืžื”ืกื™ื‘ื” ืฉืฆื•ื™ื ื” ืœืขื™ืœ. ื›ืืฉืจ ืื ื• ืžื“ืงืกื™ื ืขืžื•ื“ื•ืช ืขื ืžืคืชื—ื•ืช ืจืืฉื™ื™ื, ื”ื”ื‘ื“ืœ ื›ืžืขื˜ ื ืขืœื, ืื‘ืœ JSONB ืขื“ื™ื™ืŸ ืžื”ื™ืจ ืคื™ 1,3 ืž-EAV. ืฉื™ืžื• ืœื‘ ืฉืœืื™ื ื“ืงืก ื‘ืขืžื•ื“ืช JSONB ืื™ืŸ ื”ืฉืคืขื” ื›ืืŸ ืžื›ื™ื•ื•ืŸ ืฉืื™ื ื ื• ืžืฉืชืžืฉื™ื ื‘ืขืžื•ื“ืช ื”ืžืืคื™ื™ื ื™ื ื‘ืงืจื™ื˜ืจื™ื•ื ื™ ื”ื”ืขืจื›ื”.

ืœื‘ื—ื™ืจืช ื ืชื•ื ื™ื ื”ืžื‘ื•ืกืกื™ื ืขืœ ืขืจืš ื”ื ื›ืก, ื ืงื‘ืœ ืืช ื”ืชื•ืฆืื•ืช ื”ื‘ืื•ืช (ืงื ื” ืžื™ื“ื” ืจื’ื™ืœ):

ื”ื—ืœืคืช EAV ื‘-JSONB ื‘-PostgreSQL

ืืชื” ื™ื›ื•ืœ ืœืฉื™ื ืœื‘ ืฉ-JSONB ืฉื•ื‘ ืขื•ื‘ื“ ืžื”ืจ ื™ื•ืชืจ ืž-EAV ืœืœื ืื™ื ื“ืงืกื™ื, ืื‘ืœ ื›ืืฉืจ EAV ืขื ืื™ื ื“ืงืกื™ื, ื”ื•ื ืขื“ื™ื™ืŸ ืขื•ื‘ื“ ืžื”ืจ ื™ื•ืชืจ ืž-JSONB. ืื‘ืœ ืื– ืจืื™ืชื™ ืฉื”ื–ืžื ื™ื ืขื‘ื•ืจ ืฉืื™ืœืชื•ืช JSONB ื–ื”ื™ื, ื–ื” ื’ืจื ืœื™ ืœืขื•ื‘ื“ื” ืฉืื™ื ื“ืงืกื™ GIN ืœื ืขื•ื‘ื“ื™ื. ื›ื›ืœ ื”ื ืจืื” ื›ืืฉืจ ืืชื” ืžืฉืชืžืฉ ื‘ืื™ื ื“ืงืก GIN ืขืœ ืขืžื•ื“ื” ืขื ืžืืคื™ื™ื ื™ื ืžืื•ื›ืœืกื™ื, ื–ื” ื ื›ื ืก ืœืชื•ืงืฃ ืจืง ื›ืืฉืจ ืืชื” ืžืฉืชืžืฉ ื‘ืื•ืคืจื˜ื•ืจ include @>. ื”ืฉืชืžืฉืชื™ ื‘ื–ื” ื‘ื‘ื“ื™ืงื” ื—ื“ืฉื” ื•ื”ื™ื™ืชื” ืœื• ื”ืฉืคืขื” ืขืฆื•ืžื” ืขืœ ื”ื–ืžืŸ: ืจืง 0,153ms! ื–ื” ืžื”ื™ืจ ืคื™ 15000 ืž-EAV ื•ืคื™ 25000 ืžื”ืจ ื™ื•ืชืจ ืžื”ืžืคืขื™ืœ ->>.

ืื ื™ ื—ื•ืฉื‘ ืฉื–ื” ื”ื™ื” ืžืกืคื™ืง ืžื”ื™ืจ!

ื’ื•ื“ืœ ื˜ื‘ืœืช ืžืกื“ ื ืชื•ื ื™ื

ื”ื‘ื” ื ืฉื•ื•ื” ืืช ื’ื“ืœื™ ื”ื˜ื‘ืœื” ืขื‘ื•ืจ ืฉืชื™ ื”ื’ื™ืฉื•ืช. ื‘-psql ื ื•ื›ืœ ืœื”ืจืื•ืช ืืช ื”ื’ื•ื“ืœ ืฉืœ ื›ืœ ื”ื˜ื‘ืœืื•ืช ื•ื”ืื™ื ื“ืงืกื™ื ื‘ืืžืฆืขื•ืช ื”ืคืงื•ื“ื” dti+

ื”ื—ืœืคืช EAV ื‘-JSONB ื‘-PostgreSQL

ืขื‘ื•ืจ ื’ื™ืฉืช ื”-EAV, ื’ื“ืœื™ ื”ื˜ื‘ืœื” ื”ื ื‘ืกื‘ื™ื‘ื•ืช 3068 ืžื’ื”-ื‘ื™ื™ื˜ ื•ืื™ื ื“ืงืกื™ื ืฉืœ ืขื“ 3427 ืžื’ื”-ื‘ื™ื™ื˜ ืขื‘ื•ืจ ืกืš ืฉืœ 6,43 ื’'ื™ื’ื”-ื‘ื™ื™ื˜. ื’ื™ืฉืช JSONB ืžืฉืชืžืฉืช ื‘-1817 MB ืขื‘ื•ืจ ื”ื˜ื‘ืœื” ื•-318 MB ืขื‘ื•ืจ ื”ืื™ื ื“ืงืกื™ื, ืฉื”ื 2,08 GB. ื–ื” ื™ื•ืฆื ืคื™ 3 ืคื—ื•ืช! ืขื•ื‘ื“ื” ื–ื• ื”ืคืชื™ืขื” ืื•ืชื™ ืžืขื˜ ืžื›ื™ื•ื•ืŸ ืฉืื ื• ืžืื—ืกื ื™ื ืฉืžื•ืช ื ื›ืกื™ื ื‘ื›ืœ ืื•ื‘ื™ื™ืงื˜ JSONB.

ืื‘ืœ ืขื“ื™ื™ืŸ, ื”ืžืกืคืจื™ื ืžื“ื‘ืจื™ื ื‘ืขื“ ืขืฆืžื: ื‘-EAV ืื ื• ืžืื—ืกื ื™ื 2 ืžืคืชื—ื•ืช ื–ืจื™ื ืฉืœืžื™ื ืœื›ืœ ืขืจืš ืชื›ื•ื ื”, ื•ื›ืชื•ืฆืื” ืžื›ืš 8 ื‘ืชื™ื ืฉืœ ื ืชื•ื ื™ื ื ื•ืกืคื™ื. ื‘ื ื•ืกืฃ, EAV ืžืื—ืกืŸ ืืช ื›ืœ ืขืจื›ื™ ื”ื ื›ืกื™ื ื›ื˜ืงืกื˜, ื‘ืขื•ื“ ืฉ-JSONB ื™ืฉืชืžืฉ ื‘ืขืจื›ื™ื ืžืกืคืจื™ื™ื ื•ื‘ื•ืœื™ืื ื™ื™ื ื‘ืื•ืคืŸ ืคื ื™ืžื™ ื‘ืžื™ื“ืช ื”ืืคืฉืจ, ื•ื›ืชื•ืฆืื” ืžื›ืš ื˜ื‘ื™ืขืช ืจื’ืœ ืงื˜ื ื” ื™ื•ืชืจ.

ืชื•ืฆืื•ืช ืฉืœ

ื‘ืกืš ื”ื›ืœ, ืื ื™ ื—ื•ืฉื‘ ืฉืฉืžื™ืจืช ืžืืคื™ื™ื ื™ ื™ืฉื•ืช ื‘ืคื•ืจืžื˜ JSONB ื™ื›ื•ืœื” ืœื”ืงืœ ืขืœ ื”ืขื™ืฆื•ื‘ ื•ื”ืชื—ื–ื•ืงื” ืฉืœ ืžืกื“ ื”ื ืชื•ื ื™ื ืฉืœืš. ืื ืืชื” ืžืคืขื™ืœ ื”ืจื‘ื” ืฉืื™ืœืชื•ืช, ืฉืžื™ืจื” ืขืœ ื”ื›ืœ ื‘ืื•ืชื” ื˜ื‘ืœื” ื›ืžื• ื”ื™ืฉื•ืช ืชืขื‘ื•ื“ ื‘ืฆื•ืจื” ื™ืขื™ืœื” ื™ื•ืชืจ. ื•ื”ืขื•ื‘ื“ื” ืฉื–ื” ืžืคืฉื˜ ืืช ื”ืื™ื ื˜ืจืืงืฆื™ื” ื‘ื™ืŸ ื”ื ืชื•ื ื™ื ื”ื™ื ื›ื‘ืจ ื™ืชืจื•ืŸ, ืื‘ืœ ืžืกื“ ื”ื ืชื•ื ื™ื ื”ืžืชืงื‘ืœ ืงื˜ืŸ ืคื™ 3 ื‘ื ืคื—.

ื›ืžื• ื›ืŸ, ืขืœ ืกืžืš ื”ื‘ื“ื™ืงื•ืช ืฉื‘ื•ืฆืขื•, ืื ื• ื™ื›ื•ืœื™ื ืœื”ืกื™ืง ืฉื”ืคืกื“ ื”ื‘ื™ืฆื•ืขื™ื ื”ื•ื ืžืื•ื“ ืœื ืžืฉืžืขื•ืชื™. ื‘ืžืงืจื™ื ืžืกื•ื™ืžื™ื, JSONB ืืคื™ืœื• ืžื”ื™ืจ ื™ื•ืชืจ ืž-EAV, ืžื” ืฉื”ื•ืคืš ืื•ืชื• ืืคื™ืœื• ื˜ื•ื‘ ื™ื•ืชืจ. ืขื ื–ืืช, ืจืฃ ื–ื” ื›ืžื•ื‘ืŸ ืื™ื ื• ืžื›ืกื” ืืช ื›ืœ ื”ื”ื™ื‘ื˜ื™ื (ืœืžืฉืœ ื™ืฉื•ื™ื•ืช ืขื ืžืกืคืจ ื’ื“ื•ืœ ืžืื•ื“ ืฉืœ ื ื›ืกื™ื, ื’ื™ื“ื•ืœ ืžืฉืžืขื•ืชื™ ื‘ืžืกืคืจ ื”ืžืืคื™ื™ื ื™ื ืฉืœ ื ืชื•ื ื™ื ืงื™ื™ืžื™ื,...), ืื– ืื ื™ืฉ ืœืš ื”ืฆืขื•ืช ืื™ืš ืœืฉืคืจ ืื•ืชื , ืื ื ืืœ ืชื”ืกืก ืœื”ืฉืื™ืจ ื‘ืชื’ื•ื‘ื•ืช!

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”