මෑතකදී මම ඔබට සම්මත වට්ටෝරු භාවිතා කරන්නේ කෙසේදැයි කීවෙමි. PostgreSQL දත්ත සමුදායකින්. අද අපි කතා කරන්නේ කොහොමද කියලා ඔබට පටිගත කිරීම වඩාත් කාර්යක්ෂම කළ හැකිය වින්යාසයේ කිසිදු "විකෘතියක්" භාවිතා නොකර දත්ත සමුදාය තුළ - දත්ත ප්රවාහ නිසි ලෙස සංවිධානය කිරීමෙන්.

#1. කොටස් කිරීම
එය සංවිධානය කිරීම වටී කෙසේද සහ ඇයි යන්න පිළිබඳ ලිපියක් දැනටමත් පැවතුනි, නමුත් මෙහිදී අපි අපගේ රාමුව තුළ සමහර ප්රවේශයන් යෙදීමේ පුරුද්ද ගැන කතා කරමු .
"ගිය දවස්වල දේවල්..."
මුලදී, ඕනෑම MVP එකක් මෙන්, අපගේ ව්යාපෘතිය තරමක් සැහැල්ලු බරක් යටතේ ආරම්භ විය - අධීක්ෂණය සිදු කරන ලද්දේ වඩාත්ම තීරණාත්මක සේවාදායකයන් දුසිමක් සඳහා පමණි, සියලුම වගු සාපේක්ෂව සංයුක්ත විය... නමුත් කාලය ගෙවී ගිය අතර, නිරීක්ෂණය කරන ලද ධාරක ගණන වැඩි වූ අතර, නැවත වරක් එකක් සමඟ යමක් කිරීමට උත්සාහ කිරීමෙන් පසුව 1.5 TB ප්රමාණයේ වගු, මේ ආකාරයට ජීවත් වීමට හැකි වුවද, එය ඉතා අපහසු බව අපට වැටහුණි.
ඒවා බොහෝ දුරට පුරාවෘත්තීය කාල වූ අතර, PostgreSQL 9.x හි විවිධ අනුවාදයන් අදාළ වූ බැවින්, සියලුම කොටස් කිරීම "අතින්" සිදු කිරීමට සිදු විය - හරහා වගු උරුමය සහ ප්රේරක ගතිකව මාර්ගගත කිරීම EXECUTE.

ප්රතිඵලයක් ලෙස ලැබුණු විසඳුම සියලුම වගු වලට පරිවර්තනය කිරීමට තරම් විශ්වීය විය:
- හිස් "ශීර්ෂක" මාපිය වගුවක් ප්රකාශයට පත් කරන ලද අතර, එය සියල්ල විස්තර කර ඇත අවශ්ය දර්ශක සහ ප්රේරක.
- සේවාදායකයාගේ දෘෂ්ටි කෝණයෙන්, ඇතුළත් කිරීම "මූල" වගුවට සිදු කරන ලද අතර, අභ්යන්තරව උපකාරයෙන් මාර්ගගත කිරීමේ ප්රේරකය
BEFORE INSERTවාර්තාව අවශ්ය කොටසට "භෞතිකව" ඇතුළත් කරන ලදී. කොටස දැනටමත් නොතිබුනේ නම්, අපි ව්යතිරේකයක් අල්ලාගෙන... - … භාවිතා කිරීමෙන් මව් වගුවේ සැකිල්ල මත පදනම්ව නිර්මාණය කරන ලදී. අවශ්ය දිනය සීමා කරන ලද කොටසඑබැවින් දත්ත ලබා ගැනීමේදී කියවීම සිදු කරනු ලබන්නේ එහි පමණි.
PG10: පළමු උත්සාහය
නමුත් උරුමය හරහා කොටස් කිරීම ඓතිහාසිකව ක්රියාකාරී ලිවීමේ ගමනාගමනය හෝ පැවත එන කොටස් විශාල සංඛ්යාවක් හැසිරවීමට එතරම් සුදුසු වී නොමැත. උදාහරණයක් ලෙස, අවශ්ය කොටස තෝරා ගැනීම සඳහා ඇල්ගොරිතමයේ තිබූ බව කෙනෙකුට මතක තබා ගත හැකිය චතුර්ථ සංකීර්ණතාව, කොටස් 100+ සමඟ ක්රියා කරන, එය ක්රියා කරන ආකාරය ඔබ දන්නවා...
PG10 හි, සහාය ක්රියාත්මක කිරීමෙන් මෙම තත්ත්වය බෙහෙවින් ප්රශස්ත කරන ලදී . ඉතින් අපි ගබඩාව සංක්රමණය කිරීමෙන් පසු වහාම එය භාවිතා කිරීමට උත්සාහ කළෙමු, නමුත්...
අත්පොත හාරා බැලීමෙන් පසු, මෙම අනුවාදයේ ස්වදේශීයව කොටස් කරන ලද වගුව පෙනෙන පරිදි:
- දර්ශක විස්තර සඳහා සහය නොදක්වයි.
- එය ක්රියාරම්භක සඳහා සහය නොදක්වයි.
- කිසිවෙකුගේ "පැවත එන්නෙකු" විය නොහැක.
- සහාය නොදක්වන්න
INSERT ... ON CONFLICT - ස්වයංක්රීයව කොටසක් ජනනය කළ නොහැක.
නළලට රේක් එකකින් තදින් පහර දුන් නිසා, යෙදුම වෙනස් නොකර අපට ඉදිරියට යා නොහැකි බව අපට වැටහුණු අතර, අපි වැඩිදුර පර්යේෂණ මාස හයකට කල් දැමුවෙමු.
PG10: දෙවන අවස්ථාව
ඉතින්, අපි පැනනැඟුණු ගැටළු එකින් එක විසඳීමට පටන් ගත්තෙමු:
- ප්රේරක සහ
ON CONFLICTසමහර ස්ථානවල ඒවා අවශ්ය බව අපට තවමත් පෙනී ගිය නිසා, ඒවා සකස් කිරීම සඳහා අපි අතරමැදි අදියරක් සකස් කළෙමු. ප්රොක්සි වගුව. - "මාර්ගගත කිරීම" ඉවත් කළා ප්රේරක වලින් - එනම්, සිට
EXECUTE. - ඔවුන් එය වෙනම එළියට ගත්තා සියලුම දර්ශක සහිත සැකිලි වගුවඑවිට ඒවා ප්රොක්සි මේසයේ පවා නොපවතී.

අවසාන වශයෙන්, මේ සියල්ලෙන් පසු, ප්රධාන වගුව ස්වදේශීයව කොටස් කරන ලදී. නව කොටසක් නිර්මාණය කිරීම තවමත් යෙදුමේ වගකීමකි.
අපි ශබ්දකෝෂ දැක්කා
ඕනෑම විශ්ලේෂණ පද්ධතියක් මෙන්, අපට ද තිබුණි "කරුණු" සහ "කොටස්" (ශබ්දකෝෂ). උදාහරණයක් ලෙස, අපගේ නඩුවේදී, සමාන මන්දගාමී විමසුම් හෝ විමසුමේම පෙළ.
අපගේ "කරුණු" දිගු කාලයක් තිස්සේ දිනෙන් දින කොටස් කර තිබුණි, එබැවින් අපට ඒවා බාධාවකින් තොරව යල් පැන ගිය කොටස් පහසුවෙන් මකා දැමිය හැකිය (සියල්ලට පසු, ඒවා ලොග් විය!). නමුත් ශබ්ද කෝෂ ටිකක් ගැටලුවක් විය...
මම කියන්නේ නැහැ ඒවා ගොඩක් තිබුණා කියලා, නමුත් ආසන්න වශයෙන් "කරුණු" 100 TB නිසා 2.5 TB ශබ්දකෝෂයක් ඇති විය.එවැනි වගුවකින් කිසිවක් පහසුවෙන් මකා දැමිය නොහැක, සාධාරණ කාලයක් තුළ එය සම්පීඩනය කළ නොහැක, එයට ලිවීම ක්රමයෙන් මන්දගාමී විය.
ඒක ශබ්දකෝෂයක් වගේ පේනවා... ඒකේ තියෙන හැම සටහනක්ම හරියටම එක පාරක් ඉදිරිපත් කරන්න ඕනේ... ඒක හරි, නමුත්!.. කවුරුත් අපිට තියෙන එක වළක්වන්නේ නැහැ සෑම දිනකම වෙනම ශබ්දකෝෂයක්ඔව්, මෙය යම් ප්රමාණයක අතිරික්තයක් ගෙන එයි, නමුත් එය ඉඩ දෙන්නේ:
- වේගයෙන් ලියන්න/කියවන්න කුඩා කොටසේ ප්රමාණය නිසා
- අඩු මතකයක් පරිභෝජනය කරයි වඩාත් සංයුක්ත දර්ශක සමඟ වැඩ කිරීමෙන්
- අඩු දත්ත ගබඩා කරන්න යල් පැන ගිය ඒවා ඉක්මනින් ඉවත් කිරීමේ හැකියාව නිසා
සමස්ත පරාසයේ පියවරවල ප්රතිඵලයක් ලෙස CPU පැටවීම ~30% කින්, තැටි පැටවීම ~50% කින් අඩු විය.:

ඒ සමඟම, අපි කුඩා බරක් සමඟින් හරියටම එකම දේ දත්ත සමුදායට ලිවීම දිගටම කරගෙන ගියෙමු.
#2. දත්ත සමුදා පරිණාමය සහ ප්රතිසංස්කරණය
ඉතින්, අපි අප සතුව ඇති දේ තීරණය කළා සෑම දිනකම කොටසක් තිබේ. දත්ත සමඟ. ඇත්තටම, CHECK (dt = '2018-10-12'::date) — සහ කොටස් කිරීමේ යතුරක් සහ වාර්තාවක් නිශ්චිත කොටසකට වැටීමට කොන්දේසියක් ඇත.
අපගේ සේවාවේ සියලුම වාර්තා නිශ්චිත දිනයක් සඳහා ගොඩනගා ඇති බැවින්, ඒවා සඳහා වන දර්ශක “බෙදී නොමැති කාලවල” සිට එලෙසම පවතී. (සේවාදායකය, දිනය, සැලසුම් සැකිල්ල), (සේවාදායකය, දිනය, සැලසුම් නෝඩය), (දිනය, දෝෂ පන්තිය, සේවාදායකය)...
නමුත් දැන් සෑම කොටසකම ජීවත් වන මිනිසුන් සිටිති. ඔබේම පිටපත් එවැනි එක් එක් දර්ශකය... සහ එක් එක් කොටස තුළ දිනය නියතයකි… දැන් අපි එවැනි එක් එක් දර්ශකයේ සිටින බව පෙනේ අපි නියතයක් ඇතුළත් කරන්නෙමු එක් ක්ෂේත්රයක් ලෙස, එහි ප්රමාණය සහ සෙවුම් කාලය යන දෙකම වැඩි කරයි, නමුත් ප්රතිඵල ලබා නොදේ. අපි අපටම උගුලක් දමා ඇත, අපොයි...

ප්රශස්තිකරණයේ දිශාව පැහැදිලිය - හුදෙක් සියලුම දර්ශක වලින් දින ක්ෂේත්රය ඉවත් කරන්න. කොටස් කරන ලද වගු මත. අපගේ පරිමාවන් සමඟ, ලාභය ආසන්න වේ සතියකට 1 TB!
දැන් අපි සටහන් කර ගනිමු මෙම ටෙරාබයිට් තවමත් කෙසේ හෝ ලිවිය යුතු බව. එනම්, අපිත් තැටිය දැන් අඩුවෙන් පූරණය විය යුතුය.සතියක් පුරාවට අප සිදු කළ පිරිසිදු කිරීමේ ප්රතිඵල මෙම පින්තූරයේ පැහැදිලිව දැක්වේ:

#3. උපරිම බර පතුරුවන්න
කාර්යබහුල පද්ධති සමඟ ඇති විශාල ගැටළු වලින් එකක් වන්නේ අතිරික්ත සමමුහුර්තකරණය සමහර සැත්කම් සඳහා එය අවශ්ය නොවේ. සමහර විට එය "අපි නොදැක්කා නිසා", සමහර විට එය "පහසුයි", නමුත් ඉක්මනින් හෝ පසුව අපට එයින් මිදීමට සිදුවේ.
අපි කලින් පින්තූරය විශාලනය කර බලමු, අපට තැටියක් ඇති බව. ද්විත්ව විස්තාරය සහිත බරක් යටතේ "පොම්ප" යාබද කියවීම් අතර, එවැනි මෙහෙයුම් ගණනාවක් සමඟ පැහැදිලිවම "සංඛ්යානමය වශයෙන්" සිදු නොවිය යුතුය:

මෙය සාක්ෂාත් කර ගැනීම තරමක් පහසුය. අප සතුව දැනටමත් අධීක්ෂණ පද්ධතියක් ක්රියාත්මක විය. සේවාදායක 1000 කට ආසන්න ප්රමාණයක්, සෑම එකක්ම වෙනම තාර්කික නූල් එකකින් සකසනු ලබන අතර, සෑම නූල් එකක්ම නිශ්චිත සංඛ්යාතයකින් දත්ත සමුදායට යැවීම සඳහා සමුච්චිත තොරතුරු ඩම්ප් කරයි, ආසන්න වශයෙන් මේ ආකාරයට:
setInterval(sendToDB, interval)මෙහි ගැටලුව හරියටම පවතින්නේ සියලුම ප්රවාහයන් එකම වේලාවක ආරම්භ වේ., ඒ නිසා ඔවුන්ගේ යැවීමේ වේලාවන් සෑම විටම පාහේ "කාරණයට" සමපාත වේ. අපොයි #2...
වාසනාවකට මෙන්, මෙය නිවැරදි කිරීම තරමක් පහසුය, "අහඹු" විසිරීමක් එකතු කිරීම කාලය අනුව:
setInterval(sendToDB, interval * (1 + 0.1 * (Math.random() - 0.5)))#4. අපට අවශ්ය දේ අපි හැඹිලිගත කරමු.
ඉහළ බර පැටවීමේ තුන්වන සාම්ප්රදායික ගැටළුව වන්නේ හැඹිලියක් නැත ඔහු කොහෙද ඉන්නේ? හැකි විය.
උදාහරණයක් ලෙස, අපි සැලසුම් නෝඩ් විශ්ලේෂණය කිරීමට හැකි කළා (මේ සියල්ල Seq Scan on users), නමුත් වහාම ඔවුන් පොදුවේ සමාන යැයි සිතුවා - ඔවුන්ට අමතක විය.
නැහැ, ඇත්ත වශයෙන්ම, දත්ත සමුදායට නැවත කිසිවක් ලියා නැත, මෙය ප්රේරකය මගින් කපා හරිනු ලැබේ. INSERT ... ON CONFLICT DO NOTHINGනමුත් මෙම දත්ත තවමත් දත්ත සමුදායට ළඟා වන අතර, ඒ සමඟම අනවශ්ය ඒවා පවා. ගැටුම පරීක්ෂා කිරීමට කියවීම මට ඒක කරන්නම වෙනවා. අපොයි #3...
හැඹිලිගත කිරීම සක්රීය කිරීමට පෙර/පසු දත්ත සමුදායට යවන ලද වාර්තා ගණනෙහි වෙනස පැහැදිලිය:

සහ ගබඩාවේ බර අඩු වීමත් සමඟ මෙය සිදු වේ:

එකතුව
"දිනකට ටෙරාබයිට්" යනු බියජනක ශබ්දයක් පමණි. ඔබ සියල්ල නිවැරදිව කළහොත්, එය බයිට් 2^40 / තත්පර 86400 = ~12.5MB/s, ඩෙස්ක්ටොප් IDE ඉස්කුරුප්පු වලට පවා රඳවා ගත හැකි. 🙂
නමුත් බැරෑරුම් ලෙස, දිවා කාලයේදී දස ගුණයක බරක් "ඇලවීම" සමඟ වුවද, ඔබට නවීන SSD වල හැකියාවන් තුළට පහසුවෙන් ගැලපේ.

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