PostgreSQL හි EAV JSONB සමඟ ප්‍රතිස්ථාපනය කිරීම

TL; DR: JSONB හට විමසුම් කාර්ය සාධනය කැප නොකර දත්ත සමුදා ක්‍රම සංවර්ධනය බෙහෙවින් සරල කළ හැක.

හැඳින්වීම

සම්බන්ධක දත්ත සමුදායක (දත්ත සමුදාය) ලෝකයේ පැරණිතම භාවිත අවස්ථා වලින් එකකට සම්භාව්‍ය උදාහරණයක් දෙමු: අපට ආයතනයක් ඇති අතර, අපට මෙම ආයතනයේ ඇතැම් ගුණාංග (ගුණාංග) සුරැකීමට අවශ්‍ය වේ. නමුත් සෑම අවස්ථාවකම එකම ගුණාංග සමූහයක් නොතිබිය හැකි අතර අනාගතයේදී තවත් ගුණාංග එකතු විය හැක.

මෙම ගැටළුව විසඳීමට ඇති පහසුම ක්‍රමය නම් එක් එක් දේපල වටිනාකම සඳහා දත්ත සමුදා වගුවේ තීරුවක් නිර්මාණය කිරීම සහ නිශ්චිත ආයතනික අවස්ථාවක් සඳහා අවශ්‍ය ඒවා පිරවීමයි. මහා! ගැටලුව විසඳී ඇත... ඔබේ වගුවේ මිලියන ගණනක් වාර්තා අඩංගු වන තෙක් සහ ඔබට නව වාර්තාවක් එක් කිරීමට අවශ්‍ය වන තුරු.

EAV රටාව සලකා බලන්න (භූතාර්ථය-ගුණාංග-අගය), එය බොහෝ විට සිදු වේ. එක් වගුවක ආයතන (වාර්තා) අඩංගු වේ, තවත් වගුවක දේපල නම් (ගුණාංග) අඩංගු වන අතර තුන්වන වගුවකින් ආයතන ඒවායේ ගුණාංග සමඟ සම්බන්ධ කර වත්මන් ආයතනය සඳහා එම ගුණාංගවල වටිනාකම අඩංගු වේ. මෙමගින් ඔබට විවිධ වස්තු සඳහා විවිධ ගුණාංග කට්ටල තිබීමේ හැකියාව ලබා දෙන අතර, දත්ත සමුදා ව්‍යුහය වෙනස් නොකර පියාසර කරන විට ගුණාංග එක් කිරීමටද හැකියාව ලැබේ.

කෙසේ වෙතත්, EVA ප්‍රවේශයේ යම් අවාසියක් නොතිබුනේ නම් මම මෙම සටහන ලියන්නේ නැත. එබැවින්, උදාහරණයක් ලෙස, එක් එක් ගුණාංග 1 බැගින් ඇති ආයතන එකක් හෝ කිහිපයක් ලබා ගැනීම සඳහා, විමසුමට සම්බන්ධ කිරීම් 2 ක් අවශ්‍ය වේ: පළමුවැන්න ගුණාංග වගුව සමඟ සම්බන්ධ වීම, දෙවැන්න අගයන් වගුව සමඟ සම්බන්ධ වීමකි. ආයතනයකට ගුණාංග 2ක් තිබේ නම්, සම්බන්ධවීම් 4ක් අවශ්‍ය වේ! අතිරේකව, සියලුම ගුණාංග සාමාන්‍යයෙන් තන්තු ලෙස ගබඩා කර ඇති අතර, එහි ප්‍රතිඵලය වන්නේ ප්‍රතිඵලය සහ WHERE වගන්තිය යන දෙකටම ටයිප් වාත්තු කිරීමයි. ඔබ බොහෝ විමසුම් ලියන්නේ නම්, සම්පත් භාවිතය සම්බන්ධයෙන් මෙය බෙහෙවින් නාස්තියකි.

මෙම පැහැදිලි අඩුපාඩු තිබියදීත්, මෙම ආකාරයේ ගැටළු විසඳීම සඳහා EAV දිගු කාලයක් තිස්සේ භාවිතා කර ඇත. මේවා නොවැළැක්විය හැකි අඩුපාඩු වූ අතර වඩා හොඳ විකල්පයක් නොතිබුණි.
නමුත් පසුව PostgreSQL හි නව “තාක්ෂණයක්” දර්ශනය විය.

PostgreSQL 9.4 සමඟින් පටන් ගෙන, JSON ද්විමය දත්ත ගබඩා කිරීමට JSONB දත්ත වර්ගය එක් කරන ලදී. මෙම ආකෘතියෙන් JSON ගබඩා කිරීම සාමාන්‍යයෙන් JSON සරල පෙළට වඩා ටිකක් වැඩි ඉඩක් සහ කාලයක් ගත වුවද, එය මත මෙහෙයුම් සිදු කිරීම වඩා වේගවත් වේ. JSONB සුචිගත කිරීමට ද සහය දක්වයි, එය විමසුම් වඩාත් වේගවත් කරයි.

JSONB දත්ත වර්ගය අපගේ ආයතන වගුවට JSONB තීරුවක් පමණක් එක් කිරීමෙන් අපහසු EAV රටාව ප්‍රතිස්ථාපනය කිරීමට ඉඩ සලසයි, දත්ත සමුදා සැලසුම බෙහෙවින් සරල කරයි. නමුත් බොහෝ දෙනා තර්ක කරන්නේ මෙය ඵලදායිතාවයේ අඩුවීමක් සමඟ විය යුතු බවයි... ඒ නිසයි මම මේ ලිපිය ලිව්වේ.

පරීක්ෂණ දත්ත සමුදායක් සැකසීම

මෙම සංසන්දනය සඳහා, මම $9.5 ගොඩනැගීමේ PostgreSQL 80 හි නැවුම් ස්ථාපනයක් මත දත්ත සමුදාය නිර්මාණය කළෙමි. ඩිජිටල් ඕෂන්ස් Ubuntu 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"
  } 
}

ඉතින් දැන් අපිට විකල්ප දෙකටම එකම දත්ත තියෙනවා. වැඩ කිරීමේදී ක්‍රියාත්මක කිරීම් සංසන්දනය කිරීම ආරම්භ කරමු!

ඔබේ නිර්මාණය සරල කරන්න

දත්ත සමුදා සැලසුම බෙහෙවින් සරල කර ඇති බව කලින් ප්‍රකාශ කරන ලදී: EAV සඳහා වගු තුනක් භාවිතා කිරීම වෙනුවට ගුණාංග සඳහා JSONB තීරුවක් භාවිතා කිරීමෙන් එක් වගුවක්. නමුත් මෙය ඉල්ලීම් වලින් පිළිබිඹු වන්නේ කෙසේද? එක් ආයතන දේපලක් යාවත්කාලීන කිරීම මේ ආකාරයෙන් පෙනේ:

-- 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 මෙතැනදී දිනයි! JSONB වස්තුවෙන් පෙළ අගයක් ලෙස වර්ණය ලබා ගැනීමට අපි JSON ->> ක්‍රියාකරු භාවිතා කරමු. @> ක්‍රියාකරු භාවිතයෙන් 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 සඳහා අවශ්‍ය සන්ධිවලට දර්ශක භාවිතා කළ නොහැක (විදේශීය යතුරු ක්ෂේත්‍ර සුචිගත කර නොමැත). මෙයින් පසු මම EAV අගය වගුවේ විදේශීය යතුරු තීරු 2 මත දර්ශකයක් මෙන්ම දර්ශකයක් නිර්මාණය කළෙමි. ජින් JSONB තීරුවක් සඳහා.

දත්ත යාවත්කාලීන කාලය අනුව (ms වලින්) පහත ප්‍රතිඵල පෙන්වයි. පරිමාණය ලඝුගණක බව සලකන්න:

PostgreSQL හි EAV JSONB සමඟ ප්‍රතිස්ථාපනය කිරීම

ඉහත සඳහන් කළ හේතුව නිසා, ඔබ දර්ශක භාවිතා නොකරන්නේ නම්, JSONB EAV වඩා (> 50000-x) වේගවත් බව අපට පෙනේ. අපි ප්‍රාථමික යතුරු සමඟ තීරු සුචිගත කළ විට, වෙනස බොහෝ දුරට අතුරුදහන් වේ, නමුත් JSONB තවමත් EAV වඩා 1,3 ගුණයකින් වේගවත් වේ. අපි ඇගයීම් නිර්ණායකවල දේපල තීරුව භාවිතා නොකරන බැවින් JSONB තීරුවේ ඇති දර්ශකයට මෙහි බලපෑමක් නොමැති බව සලකන්න.

දේපල වටිනාකම මත පදනම්ව දත්ත තේරීම සඳහා, අපට පහත ප්‍රතිඵල ලැබේ (සාමාන්‍ය පරිමාණය):

PostgreSQL හි EAV JSONB සමඟ ප්‍රතිස්ථාපනය කිරීම

JSONB නැවතත් දර්ශක නොමැතිව EAV වලට වඩා වේගයෙන් ක්‍රියා කරන බව ඔබට දැක ගත හැක, නමුත් EAV දර්ශක සහිත විට, එය තවමත් JSONB ට වඩා වේගයෙන් ක්‍රියා කරයි. නමුත් පසුව මම JSONB විමසුම් සඳහා වේලාවන් සමාන බව දුටුවෙමි, මෙය GIN දර්ශක ක්‍රියා නොකරන බවට මා පොළඹවන ලදී. පැහැදිලිවම ඔබ ජනාකීර්ණ ගුණාංග සහිත තීරුවක GIN දර්ශකයක් භාවිතා කරන විට, එය ක්‍රියාත්මක වන්නේ ඇතුලත් ක්‍රියාකරු @> භාවිතා කරන විට පමණි. මම මෙය නව පරීක්ෂණයකදී භාවිතා කළ අතර එය කාලයට විශාල බලපෑමක් ඇති කළේය: 0,153ms පමණි! මෙය EAV ට වඩා 15000 ගුණයකින් වේගවත් වන අතර ->> ක්‍රියාකරුට වඩා 25000 ගුණයකින් වේගවත් වේ.

මම හිතන්නේ එය ප්රමාණවත් තරම් වේගවත් විය!

දත්ත සමුදා වගු විශාලත්වය

ප්රවේශයන් දෙකම සඳහා වගු ප්රමාණ සංසන්දනය කරමු. psql වලදී අපට විධානය භාවිතයෙන් සියලුම වගු සහ දර්ශකවල ප්‍රමාණය පෙන්විය හැක dti+

PostgreSQL හි EAV JSONB සමඟ ප්‍රතිස්ථාපනය කිරීම

EAV ප්‍රවේශය සඳහා, වගු ප්‍රමාණය 3068 MB පමණ වන අතර මුළු 3427 GB සඳහා 6,43 MB දක්වා දර්ශක වේ. JSONB ප්‍රවේශය වගුව සඳහා 1817 MB සහ දර්ශක සඳහා 318 MB භාවිතා කරයි, එය 2,08 GB වේ. එය 3 ගුණයකින් අඩු වේ! අපි සෑම JSONB වස්තුවකම දේපල නම් ගබඩා කරන නිසා මෙම කරුණ මා ටිකක් පුදුමයට පත් කළේය.

නමුත් තවමත්, සංඛ්‍යා තමන් වෙනුවෙන්ම කථා කරයි: EAV හි අපි එක් එක් ගුණාංග අගයකට නිඛිල විදේශීය යතුරු 2 ක් ගබඩා කර ඇති අතර එමඟින් අමතර දත්ත බයිට් 8 ක් ලැබේ. මීට අමතරව, EAV සියළුම දේපල අගයන් පෙළ ලෙස ගබඩා කරන අතර, JSONB හැකි සෑම විටම සංඛ්‍යාත්මක සහ බූලියන් අගයන් අභ්‍යන්තරව භාවිතා කරනු ඇත, එහි ප්‍රතිඵලයක් ලෙස කුඩා අඩිපාරක් ලැබේ.

ප්රතිඵල

සමස්තයක් වශයෙන්, JSONB ආකෘතියෙන් ආයතන ගුණාංග සුරැකීමෙන් ඔබේ දත්ත සමුදාය සැලසුම් කිරීම සහ නඩත්තු කිරීම වඩාත් පහසු කළ හැකි යැයි මම සිතමි. ඔබ බොහෝ විමසුම් ක්‍රියාත්මක කරන්නේ නම්, සියල්ල එකම වගුවක ස්ථිතිකය ලෙස තබා ගැනීම ඇත්ත වශයෙන්ම වඩා කාර්යක්ෂමව ක්‍රියා කරයි. තවද මෙය දත්ත අතර අන්තර්ක්‍රියා සරල කරන බව දැනටමත් ප්ලස් වේ, නමුත් ප්‍රතිඵලයක් ලෙස ලැබෙන දත්ත සමුදාය පරිමාවෙන් 3 ගුණයකින් කුඩා වේ.

එසේම, සිදු කරන ලද පරීක්ෂණ මත පදනම්ව, කාර්ය සාධන පාඩු ඉතා සුළු බව අපට නිගමනය කළ හැකිය. සමහර අවස්ථාවලදී, JSONB EAV වලට වඩා වේගවත් වන අතර, එය වඩාත් හොඳ කරයි. කෙසේ වෙතත්, ඇත්ත වශයෙන්ම මෙම මිණුම් ලකුණ සියලු අංශ ආවරණය නොකරයි (උදා. ඉතා විශාල දේපල සංඛ්‍යාවක් සහිත ආයතන, පවතින දත්තවල ගුණවල සැලකිය යුතු වැඩි වීමක්,...), එබැවින් ඔබට ඒවා වැඩිදියුණු කරන ආකාරය පිළිබඳ කිසියම් යෝජනා තිබේ නම් , කරුණාකර අදහස් දැක්වීමට නිදහස් වන්න!

මූලාශ්රය: www.habr.com

DDoS ආරක්ෂාව, VPS VDS සේවාදායකයන් සහිත අඩවි සඳහා විශ්වාසදායක සත්කාරකත්වය මිලදී ගන්න 🔥 DDoS ආරක්ෂාව, VPS VDS සේවාදායකයන් සහිත විශ්වාසදායක වෙබ් අඩවි සත්කාරකත්වය මිලදී ගන්න | ProHoster