சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB

தரமான சமையல் குறிப்புகளைப் பயன்படுத்தி எப்படி என்று சமீபத்தில் நான் உங்களுக்குச் சொன்னேன் SQL வாசிப்பு வினவல்களின் செயல்திறனை அதிகரிக்கவும் PostgreSQL தரவுத்தளத்திலிருந்து. எப்படி என்பதைப் பற்றி இன்று பேசுவோம் பதிவு மிகவும் திறமையாக செய்ய முடியும் தரவுத்தளத்தில் உள்ளமைவில் எந்த “திருப்பங்களையும்” பயன்படுத்தாமல் - தரவு ஓட்டங்களை சரியாக ஒழுங்கமைப்பதன் மூலம்.

சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB

#1. பிரித்தல்

எப்படி, ஏன் ஏற்பாடு செய்வது என்பது பற்றிய கட்டுரை "கோட்பாட்டில்" பயன்படுத்தப்பட்ட பகிர்வு ஏற்கனவே உள்ளது, இங்கே நாம் சில அணுகுமுறைகளைப் பயன்படுத்துவதற்கான நடைமுறையைப் பற்றி பேசுவோம் நூற்றுக்கணக்கான PostgreSQL சேவையகங்களுக்கான கண்காணிப்பு சேவை.

"நாட்கள் போன விஷயங்கள்..."

ஆரம்பத்தில், எந்த MVP ஐப் போலவே, எங்கள் திட்டமும் மிகவும் குறைந்த சுமையின் கீழ் தொடங்கியது - மிக முக்கியமான பத்து சேவையகங்களுக்கு மட்டுமே கண்காணிப்பு மேற்கொள்ளப்பட்டது, எல்லா அட்டவணைகளும் ஒப்பீட்டளவில் கச்சிதமாக இருந்தன ... ஆனால் நேரம் செல்ல செல்ல, கண்காணிக்கப்பட்ட ஹோஸ்ட்களின் எண்ணிக்கை மேலும் மேலும் அதிகரித்தது. , மீண்டும் ஒருமுறை ஏதாவது ஒன்றைச் செய்ய முயற்சித்தோம் அட்டவணைகள் 1.5TB அளவு, இப்படி தொடர்ந்து வாழ்வது சாத்தியம் என்றாலும், மிகவும் சிரமமாக இருப்பதை உணர்ந்தோம்.

காலங்கள் ஏறக்குறைய காவிய காலங்களைப் போலவே இருந்தன, PostgreSQL 9.x இன் வெவ்வேறு பதிப்புகள் பொருத்தமானவையாக இருந்தன, எனவே அனைத்து பகிர்வுகளையும் "கைமுறையாக" செய்ய வேண்டியிருந்தது. அட்டவணை பரம்பரை மற்றும் தூண்டுதல்கள் டைனமிக் கொண்ட ரூட்டிங் EXECUTE.

சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB
இதன் விளைவாக தீர்வு உலகளாவியதாக மாறியது, அது அனைத்து அட்டவணைகளுக்கும் மொழிபெயர்க்கப்படலாம்:

  • ஒரு வெற்று "தலைப்பு" பெற்றோர் அட்டவணை அறிவிக்கப்பட்டது, இது அனைத்தையும் விவரிக்கிறது தேவையான குறியீடுகள் மற்றும் தூண்டுதல்கள்.
  • வாடிக்கையாளரின் பார்வையில் இருந்து பதிவு "ரூட்" அட்டவணையில் செய்யப்பட்டது மற்றும் உள்நாட்டில் பயன்படுத்தப்பட்டது ரூட்டிங் தூண்டுதல் BEFORE INSERT தேவையான பிரிவில் பதிவு "உடல் ரீதியாக" செருகப்பட்டது. இதுவரை அப்படி எதுவும் இல்லை என்றால், நாங்கள் ஒரு விதிவிலக்கு மற்றும்...
  • … பயன்படுத்தி CREATE TABLE ... (LIKE ... INCLUDING ...) பெற்றோர் அட்டவணையின் வார்ப்புருவின் அடிப்படையில் உருவாக்கப்பட்டது விரும்பிய தேதியில் கட்டுப்பாடு கொண்ட பிரிவுஅதனால் தரவு மீட்டெடுக்கப்படும் போது, ​​அதில் மட்டுமே வாசிப்பு செய்யப்படுகிறது.

PG10: முதல் முயற்சி

ஆனால் பரம்பரை மூலம் பிரித்தல் என்பது செயலில் எழுதும் ஸ்ட்ரீம் அல்லது அதிக எண்ணிக்கையிலான குழந்தைப் பகிர்வுகளைக் கையாள்வதற்கு வரலாற்று ரீதியாக மிகவும் பொருத்தமானதாக இல்லை. எடுத்துக்காட்டாக, தேவையான பகுதியைத் தேர்ந்தெடுப்பதற்கான அல்காரிதம் இருந்ததை நீங்கள் நினைவுபடுத்தலாம் இருபடி சிக்கலானது, இது 100+ பிரிவுகளுடன் செயல்படுகிறது என்பதை நீங்களே புரிந்துகொள்கிறீர்கள்...

PG10 இல் இந்த நிலைமை ஆதரவை செயல்படுத்துவதன் மூலம் பெரிதும் மேம்படுத்தப்பட்டது சொந்த பகிர்வு. எனவே, சேமிப்பகத்தை நகர்த்தியவுடன் உடனடியாக அதைப் பயன்படுத்த முயற்சித்தோம், ஆனால்...

கையேட்டைத் தோண்டிய பிறகு, இந்த பதிப்பில் உள்ள பூர்வீகமாகப் பிரிக்கப்பட்ட அட்டவணை:

  • குறியீட்டு விளக்கங்களை ஆதரிக்காது
  • அதில் தூண்டுதல்களை ஆதரிக்காது
  • யாருடைய சந்ததியாகவும் இருக்க முடியாது
  • ஆதரிக்க வேண்டாம் INSERT ... ON CONFLICT
  • ஒரு பகுதியை தானாக உருவாக்க முடியாது

ரேக் மூலம் நெற்றியில் வலிமிகுந்த அடியைப் பெற்றதால், விண்ணப்பத்தை மாற்றியமைக்காமல் செய்ய இயலாது என்பதை உணர்ந்து, மேலும் ஆராய்ச்சியை ஆறு மாதங்களுக்கு ஒத்திவைத்தோம்.

PG10: இரண்டாவது வாய்ப்பு

எனவே, எழுந்த பிரச்சினைகளை ஒவ்வொன்றாக தீர்க்க ஆரம்பித்தோம்:

  1. ஏனெனில் தூண்டுதல்கள் மற்றும் ON CONFLICT நாங்கள் இன்னும் அங்கும் இங்கும் தேவைப்படுவதைக் கண்டறிந்தோம், எனவே அவற்றைச் செயல்படுத்த ஒரு இடைநிலை நிலையை உருவாக்கினோம் பதிலாள் அட்டவணை.
  2. "ரூட்டிங்" அகற்றப்பட்டது தூண்டுதல்களில் - அதாவது, இருந்து EXECUTE.
  3. தனித்தனியாக வெளியே எடுத்தார்கள் அனைத்து குறியீடுகள் கொண்ட டெம்ப்ளேட் அட்டவணைஅதனால் அவை ப்ராக்ஸி அட்டவணையில் கூட இல்லை.

சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB
இறுதியாக, இவை அனைத்திற்கும் பிறகு, நாங்கள் பிரதான அட்டவணையை பூர்வீகமாகப் பிரித்தோம். புதிய பிரிவை உருவாக்குவது இன்னும் பயன்பாட்டின் மனசாட்சிக்கு விடப்பட்டுள்ளது.

"அறுத்தல்" அகராதிகள்

எந்த பகுப்பாய்வு அமைப்பையும் போலவே, எங்களிடம் இருந்தது "உண்மைகள்" மற்றும் "வெட்டுகள்" (அகராதிகள்). எங்கள் விஷயத்தில், இந்த திறனில் அவர்கள் செயல்பட்டனர், எடுத்துக்காட்டாக, டெம்ப்ளேட் உடல் இதே போன்ற மெதுவான வினவல்கள் அல்லது வினவலின் உரை.

"உண்மைகள்" ஏற்கனவே நீண்ட காலமாக நாளுக்கு நாள் பிரிக்கப்பட்டுள்ளன, எனவே காலாவதியான பகுதிகளை நாங்கள் அமைதியாக நீக்கிவிட்டோம், மேலும் அவை எங்களைத் தொந்தரவு செய்யவில்லை (பதிவுகள்!). ஆனால் அகராதிகளில் ஒரு சிக்கல் இருந்தது...

அவற்றில் நிறைய இருந்தன என்று சொல்ல முடியாது, ஆனால் தோராயமாக 100TB "உண்மைகள்" 2.5TB அகராதியை உருவாக்கியது. அத்தகைய அட்டவணையில் இருந்து எதையும் நீங்கள் வசதியாக நீக்க முடியாது, போதுமான நேரத்தில் அதை சுருக்க முடியாது, மேலும் அதற்கு எழுதுவது படிப்படியாக மெதுவாகிவிட்டது.

ஒரு அகராதி போல... அதில், ஒவ்வொரு பதிவும் ஒரு முறை சரியாக வழங்கப்பட வேண்டும்... இது சரிதான், ஆனால்!.. யாரும் நம்மைத் தடுப்பதில்லை. ஒவ்வொரு நாளும் தனி அகராதி! ஆம், இது ஒரு குறிப்பிட்ட பணிநீக்கத்தைக் கொண்டுவருகிறது, ஆனால் இது அனுமதிக்கிறது:

  • வேகமாக எழுத / படிக்க சிறிய பகுதியின் அளவு காரணமாக
  • குறைந்த நினைவகத்தை உட்கொள்ளும் மேலும் கச்சிதமான குறியீடுகளுடன் வேலை செய்வதன் மூலம்
  • குறைவான தரவுகளை சேமிக்கவும் காலாவதியானதை விரைவாக அகற்றும் திறன் காரணமாக

நடவடிக்கைகளின் முழு சிக்கலான விளைவாக CPU சுமை ~30%, வட்டு சுமை ~50% குறைந்துள்ளது:

சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB
அதே நேரத்தில், குறைவான சுமையுடன், தரவுத்தளத்தில் அதே விஷயத்தை தொடர்ந்து எழுதினோம்.

#2. தரவுத்தள பரிணாமம் மற்றும் மறுசீரமைப்பு

எனவே எங்களிடம் இருப்பதை நாங்கள் தீர்த்துக் கொண்டோம் ஒவ்வொரு நாளும் அதன் சொந்த பிரிவு உள்ளது தரவுகளுடன். உண்மையில், CHECK (dt = '2018-10-12'::date) — மற்றும் ஒரு பகிர்வு விசை மற்றும் ஒரு பதிவு ஒரு குறிப்பிட்ட பிரிவில் விழும் நிபந்தனை உள்ளது.

எங்கள் சேவையில் உள்ள அனைத்து அறிக்கைகளும் ஒரு குறிப்பிட்ட தேதியின் பின்னணியில் கட்டமைக்கப்படுவதால், "பகிர்வு செய்யப்படாத நேரங்கள்" முதல் அவற்றுக்கான குறியீடுகள் அனைத்து வகைகளாகும் (சேவையகம், தேதி, திட்ட வார்ப்புரு), (சேவையகம், தேதி, திட்ட முனை), (தேதி, பிழை வகுப்பு, சர்வர்)...

ஆனால் இப்போது அவர்கள் ஒவ்வொரு பிரிவிலும் வாழ்கிறார்கள் உங்கள் பிரதிகள் அத்தகைய ஒவ்வொரு குறியீடு... மேலும் ஒவ்வொரு பிரிவிற்குள்ளும் தேதி ஒரு நிலையானது... இப்போது நாம் அத்தகைய ஒவ்வொரு குறியீட்டிலும் இருக்கிறோம் என்று மாறிவிடும் ஒரு மாறிலியை உள்ளிடவும் புலங்களில் ஒன்றாக, அதன் தொகுதி மற்றும் தேடல் நேரம் இரண்டையும் அதிகரிக்கிறது, ஆனால் எந்த முடிவையும் கொண்டு வரவில்லை. அவர்கள் ரேக்கை தங்களுக்குள் விட்டுவிட்டார்கள், அச்சச்சோ...

சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB
தேர்வுமுறையின் திசை வெளிப்படையானது - எளிமையானது அனைத்து குறியீடுகளிலிருந்தும் தேதி புலத்தை அகற்றவும் பிரிக்கப்பட்ட அட்டவணையில். எங்கள் தொகுதிகள் கொடுக்கப்பட்ட, ஆதாயம் பற்றி 1TB/வாரம்!

இந்த டெராபைட் இன்னும் எப்படியாவது பதிவு செய்யப்பட வேண்டும் என்பதை இப்போது கவனிக்கலாம். அதாவது நாமும் கூட வட்டு இப்போது குறைவாக ஏற்றப்பட வேண்டும்! இந்த படம் சுத்தம் செய்வதிலிருந்து பெறப்பட்ட விளைவை தெளிவாகக் காட்டுகிறது, அதற்காக நாங்கள் ஒரு வாரம் அர்ப்பணித்தோம்:

சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB

#3. உச்ச சுமையை "பரவுதல்"

ஏற்றப்பட்ட அமைப்புகளின் பெரிய பிரச்சனைகளில் ஒன்று தேவையற்ற ஒத்திசைவு தேவையில்லாத சில செயல்பாடுகள். சில நேரங்களில் "அவர்கள் கவனிக்காததால்", சில நேரங்களில் "அது எளிதாக இருந்தது", ஆனால் விரைவில் அல்லது பின்னர் நீங்கள் அதை அகற்ற வேண்டும்.

முந்தைய படத்தைப் பெரிதாக்கி நம்மிடம் வட்டு இருப்பதைப் பார்ப்போம் இரட்டை வீச்சுடன் சுமையின் கீழ் "பம்ப்கள்" அருகிலுள்ள மாதிரிகளுக்கு இடையில், இது போன்ற பல செயல்பாடுகளுடன் தெளிவாக "புள்ளிவிவரப்படி" நடக்கக்கூடாது:

சப்லைட்டில் 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...

கேச்சிங் இயக்கப்படுவதற்கு முன்/பின் தரவுத்தளத்திற்கு அனுப்பப்பட்ட பதிவுகளின் எண்ணிக்கையில் உள்ள வேறுபாடு தெளிவாக உள்ளது:

சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB

மேலும் இது சேமிப்பக சுமையில் ஏற்படும் வீழ்ச்சியாகும்:

சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB

மொத்தம்

"டெராபைட்-ஒரு நாளைக்கு" என்பது பயமாக இருக்கிறது. நீங்கள் எல்லாவற்றையும் சரியாகச் செய்தால், இது நியாயமானது 2^40 பைட்டுகள் / 86400 வினாடிகள் = ~12.5MB/விடெஸ்க்டாப் ஐடிஇ திருகுகள் கூட வைத்திருக்கின்றன. 🙂

ஆனால் தீவிரமாக, பகலில் பத்து மடங்கு "வளைவு" சுமையுடன் கூட, நவீன SSD களின் திறன்களை நீங்கள் எளிதாக சந்திக்க முடியும்.

சப்லைட்டில் PostgreSQL இல் எழுதுகிறோம்: 1 ஹோஸ்ட், 1 நாள், 1TB

ஆதாரம்: www.habr.com

கருத்தைச் சேர்