අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB

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

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB

#1. කොටස් කිරීම

එය සංවිධානය කිරීම වටී කෙසේද සහ ඇයි යන්න පිළිබඳ ලිපියක් ව්යවහාරික කොටස් කිරීම "න්යාය තුල" දැනටමත් සිදු වී ඇත, මෙහිදී අපි අපගේ අභ්‍යන්තරයේ සමහර ප්‍රවේශයන් යෙදීමේ පුරුද්ද ගැන කතා කරමු PostgreSQL සේවාදායකයන් සිය ගණනක් සඳහා අධීක්ෂණ සේවාව.

"ගිය දවස් වල දේවල්..."

මුලදී, ඕනෑම MVP මෙන්, අපගේ ව්‍යාපෘතිය තරමක් සැහැල්ලු බරක් යටතේ ආරම්භ විය - අධීක්‍ෂණය සිදු කරන ලද්දේ වඩාත්ම තීරණාත්මක සේවාදායකයන් දහය සඳහා පමණි, සියලුම වගු සාපේක්ෂව සංයුක්ත විය ... නමුත් කාලය ගෙවී යත්ම, අධීක්‍ෂණය කරන ලද සත්කාරක සංඛ්‍යාව වඩ වඩාත් වැඩි විය. , සහ නැවත වරක් අපි එකක් සමඟ යමක් කිරීමට උත්සාහ කළෙමු වගු 1.5TB ප්‍රමාණයෙන්, මේ විදියට ජීවත් වෙන්න පුළුවන් වුණත් ඒක හරිම අපහසුයි කියලා අපිට තේරුණා.

කාලය බොහෝ දුරට එපික් වේලාවන් මෙන් විය, PostgreSQL 9.x හි විවිධ අනුවාද අදාළ විය, එබැවින් සියලුම කොටස් කිරීම "අතින්" සිදු කිරීමට සිදු විය - හරහා වගු උරුමය සහ ප්‍රේරක ගතික සමග මාර්ගගත කිරීම EXECUTE.

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB
ප්‍රති result ලය වූ විසඳුම සියලු වගු වලට පරිවර්තනය කළ හැකි තරම් විශ්වීය විය:

  • හිස් "ශීර්ෂ" මාපිය වගුවක් ප්‍රකාශ කරන ලද අතර එය සියල්ල විස්තර කරන ලදී අවශ්‍ය දර්ශක සහ ප්‍රේරක.
  • සේවාලාභියාගේ දෘෂ්ටි කෝණයෙන් වාර්තාව "මූල" වගුවේ සිදු කරන ලද අතර, අභ්යන්තරව භාවිතා කර ඇත මාර්ග ප්‍රේරකය BEFORE INSERT වාර්තාව "භෞතිකව" අවශ්ය කොටසට ඇතුල් කරන ලදී. තවම එවැන්නක් නොතිබුනේ නම්, අපි ව්යතිරේකයක් අල්ලාගෙන ...
  • … භාවිතා කිරීම මගින් CREATE TABLE ... (LIKE ... INCLUDING ...) මාපිය වගුවේ අච්චුව මත පදනම්ව නිර්මාණය කරන ලදී අපේක්ෂිත දිනයේ සීමාවක් සහිත කොටසදත්ත ලබා ගත් විට, කියවීම සිදු කරනු ලබන්නේ එහි පමණි.

PG10: පළමු උත්සාහය

නමුත් සක්‍රීය ලිවීමේ ප්‍රවාහයක් හෝ ළමා කොටස් විශාල ප්‍රමාණයක් සමඟ කටයුතු කිරීමට උරුමය හරහා බෙදීම ඓතිහාසිකව නොගැලපේ. උදාහරණයක් ලෙස, අවශ්ය කොටස තෝරා ගැනීම සඳහා ඇල්ගොරිතම ඇති බව ඔබට මතක තබා ගත හැකිය චතුරස්රාකාර සංකීර්ණත්වය, එය කොටස් 100+ සමඟ ක්‍රියා කරන බව, ඔබටම වැටහෙන්නේ කෙසේද...

PG10 හි මෙම තත්ත්වය සහය ක්‍රියාත්මක කිරීම මගින් බෙහෙවින් ප්‍රශස්ත කරන ලදී දේශීය කොටස් කිරීම. එමනිසා, ගබඩාව සංක්‍රමණය කිරීමෙන් පසු අපි වහාම එය යෙදීමට උත්සාහ කළෙමු, නමුත් ...

අත්පොත හෑරීමෙන් පසු පෙනී ගිය පරිදි, මෙම අනුවාදයේ ස්වදේශිකව කොටස් කළ වගුව වන්නේ:

  • දර්ශක විස්තර සඳහා සහය නොදක්වයි
  • එය මත ප්‍රේරක සඳහා සහය නොදක්වයි
  • කිසිවෙකුගේ "පැවතුම්" විය නොහැක
  • සහාය නොදක්වන්න INSERT ... ON CONFLICT
  • ස්වයංක්‍රීයව කොටසක් ජනනය කළ නොහැක

පෝරුවකින් නළලට වේදනාකාරී පහරක් ලැබුණු පසු, යෙදුම වෙනස් නොකර එය කළ නොහැකි බව අපට වැටහුණු අතර වැඩිදුර පර්යේෂණ මාස හයකට කල් දැමුවෙමු.

PG10: දෙවන අවස්ථාව

ඉතින්, අපි පැන නගින ගැටළු එකින් එක විසඳීමට පටන් ගත්තෙමු:

  1. ප්‍රේරක සහ ON CONFLICT අපට ඒවා තවමත් එහෙන් මෙහෙන් අවශ්‍ය බව අපට පෙනී ගිය නිසා අපි ඒවා සකස් කිරීමට අතරමැදි වේදිකාවක් සෑදුවෙමු ප්රොක්සි වගුව.
  2. "මාර්ගගත කිරීම" ඉවත් කළා ප්‍රේරක තුළ - එනම්, සිට EXECUTE.
  3. ඔවුන් එය වෙනම එළියට ගත්තා සියලුම දර්ශක සහිත සැකිලි වගුවඒ නිසා ඒවා ප්‍රොක්සි වගුවේවත් නොමැත.

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB
අවසාන වශයෙන්, මේ සියල්ලෙන් පසු, අපි ප්රධාන වගුව ස්වදේශීය ලෙස කොටස් කළෙමු. නව අංශයක් නිර්මාණය කිරීම තවමත් යෙදුමේ හෘද සාක්ෂියට ඉතිරිව ඇත.

"කියන්න" ශබ්දකෝෂ

ඕනෑම විශ්ලේෂණ පද්ධතියක මෙන් අපටත් තිබුණා "කරුණු" සහ "කප්පාදු" (ශබ්දකෝෂ). අපගේ නඩුවේදී, මෙම හැකියාව තුළ ඔවුන් ක්රියා කළා, උදාහරණයක් ලෙස, සැකිලි ශරීරය සමාන මන්දගාමී විමසුම් හෝ විමසුමේ පෙළ.

“කරුණු” දැනටමත් දිගු කලක් තිස්සේ දිනෙන් දින කොටස් කර ඇත, එබැවින් අපි සන්සුන්ව යල් පැන ගිය කොටස් මකා දැමූ අතර ඒවා අපට කරදර කළේ නැත (ලොග්!). නමුත් ශබ්දකෝෂ වල ගැටලුවක් තිබුනා...

ඒවා ගොඩක් තිබුනා කියන්න නෙවෙයි, ආසන්න වශයෙන් "කරුණු" 100TB ප්‍රතිඵලයක් ලෙස 2.5TB ශබ්දකෝෂයක් නිර්මාණය විය. ඔබට එවැනි වගුවකින් කිසිවක් පහසුවෙන් මකා දැමිය නොහැක, ඔබට එය ප්‍රමාණවත් කාලයක් තුළ සම්පීඩනය කළ නොහැක, එයට ලිවීම ක්‍රමයෙන් මන්දගාමී විය.

ශබ්දකෝෂයක් වගේ... ඒකේ හැම සටහනක්ම හරියටම එක පාරක් ඉදිරිපත් කරන්න ඕනේ... මේක හරි, ඒත්!.. කවුරුත් අපිට තියෙන එක වළක්වන්නේ නැහැ සෑම දිනකම වෙනම ශබ්ද කෝෂයක්! ඔව්, මෙය යම් අතිරික්තයක් ගෙන එයි, නමුත් එය ඉඩ දෙයි:

  • වේගයෙන් ලියන්න/කියවන්න කුඩා කොටස් ප්රමාණය නිසා
  • අඩු මතකයක් පරිභෝජනය කරයි වඩාත් සංයුක්ත දර්ශක සමඟ වැඩ කිරීමෙන්
  • අඩු දත්ත ගබඩා කරන්න යල් පැන ගිය ඒවා ඉක්මනින් ඉවත් කිරීමේ හැකියාව නිසා

සමස්ත සංකීර්ණ පියවරවල ප්රතිඵලයක් ලෙස CPU භාරය ~30% කින්, තැටි භාරය ~50% කින් අඩු විය:

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB
ඒ අතරම, අපි අඩු බරක් සහිතව, දත්ත ගබඩාවට එකම දේ ලිවීම දිගටම කරගෙන ගියෙමු.

#2. දත්ත සමුදාය පරිණාමය සහ නැවත සකස් කිරීම

ඒ නිසා අපි අපිට තියෙන දේ මත පදිංචි වුණා සෑම දිනකම තමන්ගේම අංශයක් ඇත දත්ත සමඟ. ඇත්තටම, CHECK (dt = '2018-10-12'::date) - සහ කොටස් කිරීමේ යතුරක් සහ වාර්තාවක් නිශ්චිත කොටසකට වැටීම සඳහා කොන්දේසියක් ඇත.

අපගේ සේවාවේ ඇති සියලුම වාර්තා නිශ්චිත දිනයක සන්දර්භය තුළ ගොඩනගා ඇති බැවින්, "බෙදා නොගත් කාලවල" සිට ඒවා සඳහා දර්ශක සියලු වර්ගවල වේ (සේවාදායකය, දිනය, සැලසුම් සැකිල්ල), (සේවාදායකය, දිනය, සැලසුම් නෝඩය), (දිනය, දෝෂ පන්තිය, සේවාදායකය)...

නමුත් දැන් ඔවුන් සෑම අංශයකම ජීවත් වෙති ඔබේ පිටපත් එවැනි එක් එක් දර්ශකය... සහ එක් එක් කොටස තුළ දිනය නියතයකි... දැන් අපි එවැනි එක් එක් දර්ශකයේ සිටින බව පෙනී යයි සරලව නියතයක් ඇතුල් කරන්න ක්ෂේත්‍ර වලින් එකක් ලෙස, එහි පරිමාව සහ ඒ සඳහා සෙවුම් කාලය යන දෙකම වැඩි කරන නමුත් කිසිදු ප්‍රතිඵලයක් ගෙන එන්නේ නැත. උන් පෝරකය තමන්ටම තියලා, අපොයි...

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB
ප්රශස්තකරණයේ දිශාව පැහැදිලිය - සරලයි සියලුම දර්ශක වලින් දින ක්ෂේත්රය ඉවත් කරන්න කොටස් කරන ලද වගු මත. අපගේ පරිමාවන් අනුව, ලාභය පමණ වේ 1TB/සතියකට!

දැන් අපි සටහන් කරමු මේ ටෙරාබයිට් එක තවමත් කෙසේ හෝ පටිගත කළ යුතු බව. එනම් අපිත් තැටිය දැන් අඩුවෙන් පූරණය විය යුතුය! අපි සතියක් කැප කළ පිරිසිදු කිරීමෙන් ලබාගත් බලපෑම මෙම පින්තූරය පැහැදිලිව පෙන්වයි:

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB

#3. උච්ච බර "පැතිරීම"

පටවන ලද පද්ධතිවල විශාල කරදරයක් වන්නේ අතිරික්ත සමමුහුර්තකරණය එය අවශ්ය නොවන සමහර මෙහෙයුම්. සමහර විට "ඔවුන් නොදැන සිටි නිසා", සමහර විට "එය පහසු විය", නමුත් ඉක්මනින් හෝ පසුව ඔබ එය ඉවත් කළ යුතුය.

අපි කලින් පින්තූරය විශාලනය කර බලමු අපට තැටියක් ඇති බව ද්විත්ව විස්තාරය සහිත බර යටතේ "පොම්ප" යාබද සාම්පල අතර, පැහැදිලිවම "සංඛ්‍යානමය වශයෙන්" එවැනි මෙහෙයුම් ගණනාවක් සමඟ සිදු නොවිය යුතුය:

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB

මෙය සාක්ෂාත් කර ගැනීම තරමක් පහසුය. අපි දැනටමත් අධීක්ෂණය ආරම්භ කර ඇත සේවාදායක 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...

හැඹිලි සක්‍රීය කිරීමට පෙර/පසු දත්ත සමුදාය වෙත යවන ලද වාර්තා සංඛ්‍යාවේ වෙනස පැහැදිලිය:

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB

ගබඩා භාරයේ පහත වැටීම මෙයයි:

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB

එකතුව

"ටෙරාබයිට්-දිනකට" බියජනකයි. ඔබ සෑම දෙයක්ම නිවැරදිව කරන්නේ නම්, මෙය සාධාරණයි 2^40 බයිට් / තත්පර 86400 = ~12.5MB/sඩෙස්ක්ටොප් IDE ඉස්කුරුප්පු පවා රඳවා ඇති බව. 🙂

නමුත් බැරෑරුම් ලෙස, දිවා කාලයේදී බර පැටවීමේ දස ගුණයක “ආක්‍රමණයක්” සමඟ වුවද, ඔබට නවීන SSD වල හැකියාවන් පහසුවෙන් සපුරාලිය හැකිය.

අපි Sublight මත PostgreSQL හි ලියන්නෙමු: 1 සත්කාරක, 1 දින, 1TB

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

අදහස් එක් කරන්න