TL; DR: JSONB வினவல் செயல்திறனைத் தியாகம் செய்யாமல் தரவுத்தளத் திட்ட மேம்பாட்டை பெரிதும் எளிதாக்கும்.
அறிமுகம்
தொடர்புடைய தரவுத்தளத்தின் (தரவுத்தளத்தின்) உலகின் மிகப் பழமையான பயன்பாட்டு நிகழ்வுகளில் ஒன்றின் சிறந்த உதாரணத்தை வழங்குவோம்: எங்களிடம் ஒரு நிறுவனம் உள்ளது, மேலும் இந்த நிறுவனத்தின் சில பண்புகளை (பண்புகளை) சேமிக்க வேண்டும். ஆனால் எல்லா நிகழ்வுகளும் ஒரே மாதிரியான பண்புகளைக் கொண்டிருக்க முடியாது, மேலும் எதிர்காலத்தில் மேலும் பண்புகள் சேர்க்கப்படலாம்.
இந்தச் சிக்கலைத் தீர்ப்பதற்கான எளிதான வழி, ஒவ்வொரு சொத்து மதிப்புக்கும் தரவுத்தள அட்டவணையில் ஒரு நெடுவரிசையை உருவாக்குவது மற்றும் ஒரு குறிப்பிட்ட நிறுவன நிகழ்விற்குத் தேவையானவற்றை நிரப்புவது. நன்று! சிக்கல் தீர்க்கப்பட்டது... உங்கள் டேபிளில் மில்லியன் கணக்கான பதிவுகள் இருக்கும் வரை, நீங்கள் ஒரு புதிய பதிவைச் சேர்க்க வேண்டும்.
EAV வடிவத்தைக் கவனியுங்கள் (
இருப்பினும், ஈ.வி.ஏ அணுகுமுறையில் சில குறைபாடுகள் இல்லாவிட்டால் நான் இந்த இடுகையை எழுத மாட்டேன். எனவே, எடுத்துக்காட்டாக, ஒவ்வொன்றும் 1 பண்புக்கூறுகளைக் கொண்ட ஒன்று அல்லது அதற்கு மேற்பட்ட நிறுவனங்களைப் பெற, வினவலில் 2 இணைப்புகள் தேவை: முதலாவது பண்புக்கூறு அட்டவணையுடன் இணைவது, இரண்டாவது மதிப்புகள் அட்டவணையுடன் இணைவது. ஒரு பொருளுக்கு 2 பண்புக்கூறுகள் இருந்தால், 4 இணைப்புகள் தேவை! கூடுதலாக, அனைத்து பண்புக்கூறுகளும் பொதுவாக சரங்களாக சேமிக்கப்படுகின்றன, இதன் விளைவாக முடிவு மற்றும் WHERE பிரிவு இரண்டிற்கும் வகை வார்ப்பு ஏற்படுகிறது. நீங்கள் நிறைய வினவல்களை எழுதினால், வளங்களைப் பயன்படுத்துவதில் இது மிகவும் வீணானது.
இந்த வெளிப்படையான குறைபாடுகள் இருந்தபோதிலும், இந்த வகையான சிக்கல்களை தீர்க்க EAV நீண்ட காலமாக பயன்படுத்தப்படுகிறது. இவை தவிர்க்க முடியாத குறைபாடுகள், மேலும் சிறந்த மாற்று எதுவும் இல்லை.
ஆனால் பின்னர் PostgreSQL இல் ஒரு புதிய "தொழில்நுட்பம்" தோன்றியது...
PostgreSQL 9.4 இல் தொடங்கி, JSON பைனரி தரவைச் சேமிக்க JSONB தரவு வகை சேர்க்கப்பட்டது. இந்த வடிவமைப்பில் JSON ஐ சேமிப்பது பொதுவாக JSON என்ற எளிய உரையை விட சற்று அதிக இடத்தையும் நேரத்தையும் எடுக்கும் என்றாலும், அதன் செயல்பாடுகள் மிக வேகமாக இருக்கும். JSONB அட்டவணைப்படுத்தலையும் ஆதரிக்கிறது, இது வினவல்களை இன்னும் வேகமாக்குகிறது.
JSONB தரவு வகையானது, எங்கள் நிறுவன அட்டவணையில் ஒரு JSONB நெடுவரிசையைச் சேர்ப்பதன் மூலம் சிக்கலான EAV வடிவத்தை மாற்ற அனுமதிக்கிறது, இது தரவுத்தள வடிவமைப்பை பெரிதும் எளிதாக்குகிறது. ஆனால், இதனுடன் உற்பத்தித் திறன் குறையும் என்று பலர் வாதிடுகிறார்கள்... அதனால்தான் இந்தக் கட்டுரையை எழுதினேன்.
சோதனை தரவுத்தளத்தை அமைத்தல்
இந்த ஒப்பீட்டிற்காக, நான் $9.5 உருவாக்கத்தில் PostgreSQL 80 இன் புதிய நிறுவலில் தரவுத்தளத்தை உருவாக்கினேன்.
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 பொருளில் உள்ள சொத்தின் மதிப்பைப் புதுப்பிக்க, செயல்பாட்டைப் பயன்படுத்த வேண்டும்
இப்போது புதுப்பித்த பொருளை அதன் புதிய நிறத்தின் அடிப்படையில் தேர்ந்தெடுக்கலாம்:
-- 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 வினவல்களை எவ்வாறு எழுதுவது என்பதற்கான கூடுதல் எடுத்துக்காட்டுகளைப் பார்க்கவும்
இப்போது செயல்திறனைப் பற்றி பேச வேண்டிய நேரம் இது.
உற்பத்தித்
செயல்திறனை ஒப்பிட நான் பயன்படுத்தினேன்
தரவு புதுப்பிப்பு நேரத்தின் அடிப்படையில் பின்வரும் முடிவுகளைக் காட்டியது (மிஎஸ்களில்). அளவுகோல் மடக்கை என்பதை நினைவில் கொள்ளவும்:
மேலே கூறப்பட்ட காரணத்திற்காக, நீங்கள் குறியீடுகளைப் பயன்படுத்தாவிட்டால், EAV ஐ விட JSONB மிகவும் (> 50000-x) வேகமானது என்பதை நாங்கள் காண்கிறோம். முதன்மை விசைகளுடன் நெடுவரிசைகளை அட்டவணைப்படுத்தும்போது, வேறுபாடு கிட்டத்தட்ட மறைந்துவிடும், ஆனால் JSONB இன்னும் EAV ஐ விட 1,3 மடங்கு வேகமாக உள்ளது. மதிப்பாய்வு அளவுகோலில் உள்ள சொத்து நெடுவரிசையை நாங்கள் பயன்படுத்தாததால், JSONB நெடுவரிசையில் உள்ள குறியீடானது இங்கு எந்த விளைவையும் ஏற்படுத்தாது என்பதை நினைவில் கொள்ளவும்.
சொத்து மதிப்பின் அடிப்படையில் தரவைத் தேர்ந்தெடுப்பதற்கு, பின்வரும் முடிவுகளைப் பெறுவோம் (சாதாரண அளவு):
குறியீடுகள் இல்லாமல் EAV ஐ விட JSONB மீண்டும் வேகமாகச் செயல்படுவதை நீங்கள் கவனிக்கலாம், ஆனால் EAV இன்டெக்ஸ்களுடன் இருக்கும்போது, அது JSONB ஐ விட வேகமாகச் செயல்படும். ஆனால் JSONB வினவல்களுக்கான நேரங்கள் ஒரே மாதிரியாக இருப்பதை நான் பார்த்தேன், இது ஜிஐஎன் இன்டெக்ஸ்கள் வேலை செய்யாது என்று என்னைத் தூண்டியது. மக்கள்தொகை கொண்ட பண்புகளைக் கொண்ட நெடுவரிசையில் நீங்கள் ஜிஐஎன் குறியீட்டைப் பயன்படுத்தும் போது, @> உள்ளிட்ட ஆபரேட்டரைப் பயன்படுத்தும் போது மட்டுமே அது செயல்படும். நான் இதை ஒரு புதிய சோதனையில் பயன்படுத்தினேன், அது நேரத்தில் பெரும் தாக்கத்தை ஏற்படுத்தியது: 0,153ms மட்டுமே! இது EAV ஐ விட 15000 மடங்கு வேகமானது மற்றும் ->> ஆபரேட்டரை விட 25000 மடங்கு வேகமானது.
அது போதுமான வேகமாக இருந்தது என்று நினைக்கிறேன்!
தரவுத்தள அட்டவணை அளவு
இரண்டு அணுகுமுறைகளுக்கும் அட்டவணை அளவுகளை ஒப்பிடுவோம். psql இல் கட்டளையைப் பயன்படுத்தி அனைத்து அட்டவணைகள் மற்றும் குறியீடுகளின் அளவைக் காட்டலாம் டிடிஐ+
EAV அணுகுமுறைக்கு, அட்டவணை அளவுகள் சுமார் 3068 MB மற்றும் குறியீடுகள் 3427 MB வரை மொத்தம் 6,43 GB. JSONB அணுகுமுறை அட்டவணைக்கு 1817 MB மற்றும் குறியீடுகளுக்கு 318 MB ஐப் பயன்படுத்துகிறது, அதாவது 2,08 GB. இது 3 மடங்கு குறைவாக மாறிவிடும்! ஒவ்வொரு JSONB பொருளிலும் சொத்துப் பெயர்களைச் சேமித்து வைப்பதால் இந்த உண்மை எனக்குக் கொஞ்சம் ஆச்சரியமாக இருந்தது.
இருப்பினும், எண்கள் தங்களைத் தாங்களே பேசுகின்றன: EAV இல் ஒரு பண்புக்கூறு மதிப்பிற்கு 2 முழு எண் வெளிநாட்டு விசைகளை சேமிக்கிறோம், இதன் விளைவாக 8 பைட்டுகள் கூடுதல் தரவு கிடைக்கும். கூடுதலாக, EAV ஆனது அனைத்து சொத்து மதிப்புகளையும் உரையாக சேமிக்கிறது, அதே நேரத்தில் JSONB எண் மற்றும் பூலியன் மதிப்புகளை முடிந்தவரை உள்நாட்டில் பயன்படுத்தும், இதன் விளைவாக சிறிய தடம் கிடைக்கும்.
முடிவுகளை
ஒட்டுமொத்தமாக, JSONB வடிவமைப்பில் நிறுவன பண்புகளைச் சேமிப்பது உங்கள் தரவுத்தளத்தை வடிவமைத்து பராமரிப்பதை மிகவும் எளிதாக்கும் என்று நினைக்கிறேன். நீங்கள் நிறைய வினவல்களை இயக்குகிறீர்கள் என்றால், எல்லாவற்றையும் ஒரே அட்டவணையில் வைத்திருப்பது உண்மையில் மிகவும் திறமையாக வேலை செய்யும். இது தரவுகளுக்கு இடையிலான தொடர்புகளை எளிதாக்குகிறது என்பது ஏற்கனவே ஒரு பிளஸ் ஆகும், ஆனால் இதன் விளைவாக தரவுத்தளம் 3 மடங்கு சிறியதாக உள்ளது.
மேலும், நிகழ்த்தப்பட்ட சோதனைகளின் அடிப்படையில், செயல்திறன் இழப்புகள் மிகவும் அற்பமானவை என்று நாம் முடிவு செய்யலாம். சில சமயங்களில், EAV ஐ விட JSONB இன்னும் வேகமானது, இது இன்னும் சிறப்பாக உள்ளது. இருப்பினும், இந்த அளவுகோல் நிச்சயமாக அனைத்து அம்சங்களையும் உள்ளடக்காது (எ.கா. அதிக எண்ணிக்கையிலான பண்புகளைக் கொண்ட நிறுவனங்கள், ஏற்கனவே உள்ள தரவின் பண்புகளின் எண்ணிக்கையில் குறிப்பிடத்தக்க அதிகரிப்பு,...), எனவே அவற்றை எவ்வாறு மேம்படுத்துவது என்பது குறித்து உங்களிடம் ஏதேனும் பரிந்துரைகள் இருந்தால் , தயவு செய்து கருத்துகளில் விட்டுவிடுங்கள்!
ஆதாரம்: www.habr.com