PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ

Վերջերս ես ձեզ ասացի, թե ինչպես, օգտագործելով ստանդարտ բաղադրատոմսեր բարձրացնել SQL-ի ընթերցման հարցումների կատարումը PostgreSQL տվյալների բազայից: Այսօր մենք կխոսենք այն մասին, թե ինչպես ձայնագրությունը կարող է կատարվել ավելի արդյունավետ տվյալների բազայում՝ առանց կոնֆիգուրացիայի «շրջադարձերի» օգտագործման, պարզապես տվյալների հոսքերը ճիշտ կազմակերպելով:

PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ

#1. Բաժանում

Հոդված այն մասին, թե ինչպես և ինչու արժե կազմակերպել կիրառական բաժանումը «տեսականորեն» արդեն եղել է, այստեղ կխոսենք մեր շրջանակներում որոշ մոտեցումների կիրառման պրակտիկայի մասին մոնիտորինգի ծառայություն հարյուրավոր PostgreSQL սերվերների համար.

«Անցած օրերի բաներ…»

Սկզբում, ինչպես ցանկացած MVP, մեր նախագիծը սկսվեց բավականին թեթև ծանրաբեռնվածության տակ. մոնիտորինգն իրականացվում էր միայն տասը ամենակարևոր սերվերների համար, բոլոր աղյուսակները համեմատաբար կոմպակտ էին... Բայց ժամանակի ընթացքում վերահսկվող հոսթների թիվը գնալով ավելի էր դառնում: , և ևս մեկ անգամ փորձեցինք ինչ-որ բան անել դրանցից մեկի հետ սեղաններ 1.5TB չափով, հասկացանք, որ թեեւ կարելի էր այսպես շարունակել ապրել, բայց շատ անհարմար էր։

Ժամանակները գրեթե նման էին էպիկական ժամանակների, PostgreSQL 9.x-ի տարբեր տարբերակները տեղին էին, ուստի բոլոր բաժանումը պետք է կատարվեր «ձեռքով»՝ միջոցով: սեղանի ժառանգությունը և գործարկիչները երթուղում դինամիկով EXECUTE.

PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ
Ստացված լուծումը պարզվեց, որ բավականին ունիվերսալ է, որ այն կարող է թարգմանվել բոլոր աղյուսակներում.

  • Հայտարարվեց դատարկ «վերնագիր» մայր աղյուսակը, որը նկարագրում էր բոլորը անհրաժեշտ ցուցանիշներ և գործարկիչներ.
  • Հաճախորդի տեսանկյունից գրառումը կատարվել է «արմատային» աղյուսակում և ներքին օգտագործման միջոցով երթուղային ձգան BEFORE INSERT գրառումը «ֆիզիկապես» տեղադրվել է պահանջվող բաժնում: Եթե ​​դեռ նման բան չկար, մենք բռնեցինք բացառություն ու...
  • … օգտագործելով CREATE TABLE ... (LIKE ... INCLUDING ...) ստեղծվել է մայր աղյուսակի ձևանմուշի հիման վրա բաժին՝ ցանկալի ամսաթվի սահմանափակումովայնպես, որ երբ տվյալները վերցվում են, ընթերցումը կատարվում է միայն դրանցում:

PG10. առաջին փորձը

Բայց ժառանգության միջոցով բաժանումը պատմականորեն այնքան էլ հարմար չէ գրելու ակտիվ հոսքի կամ մեծ թվով մանկական բաժանումների հետ գործ ունենալու համար: Օրինակ, կարող եք հիշել, որ անհրաժեշտ հատվածն ընտրելու ալգորիթմն ուներ քառակուսի բարդություն, որ աշխատում է 100+ բաժիններով, դուք ինքներդ եք հասկանում, թե ինչպես...

PG10-ում այս իրավիճակը մեծապես օպտիմիզացվել է աջակցության ներդրմամբ հայրենի բաժանում. Հետևաբար, մենք անմիջապես փորձեցինք կիրառել այն պահեստը տեղափոխելուց անմիջապես հետո, բայց...

Ինչպես պարզվեց ձեռնարկը փորփրելուց հետո, այս տարբերակի բնիկ բաժանված աղյուսակը հետևյալն է.

  • չի աջակցում ինդեքսների նկարագրությունները
  • չի աջակցում դրա վրա ձգաններին
  • չի կարող լինել որևէ մեկի «հետնորդը»
  • չեն աջակցում INSERT ... ON CONFLICT
  • չի կարող ինքնաբերաբար բաժին ստեղծել

Ստանալով ճակատին փոցխով ցավոտ հարված՝ մենք հասկացանք, որ դա անհնար է անել առանց հավելվածը փոփոխելու, և հետաձգեցինք հետագա հետազոտությունները վեց ամսով։

PG10. երկրորդ հնարավորություն

Այսպիսով, մենք սկսեցինք մեկ առ մեկ լուծել ծագած խնդիրները.

  1. Քանի որ հրահրողներն ու ON CONFLICT Մենք գտանք, որ դրանք մեզ դեռ պետք են այստեղ-այնտեղ, ուստի միջանկյալ փուլ կազմեցինք դրանք մշակելու համար վստահված անձի աղյուսակ.
  2. Ազատվել է «երթուղուց» ձգանների մեջ - այսինքն, սկսած EXECUTE.
  3. Առանձին հանեցին կաղապարի աղյուսակ բոլոր ինդեքսներովայնպես, որ նրանք նույնիսկ ներկա չեն վստահված անձանց աղյուսակում:

PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ
Վերջապես այսքանից հետո հիմնական աղյուսակը բաժանեցինք բնիկ։ Նոր բաժնի ստեղծումը դեռ մնում է հավելվածի խղճին։

«Սղոցում» բառարաններ

Ինչպես ցանկացած վերլուծական համակարգում, մենք նույնպես ունեինք «փաստեր» և «կտրվածքներ» (բառարաններ): Մեր դեպքում այս կարգավիճակով նրանք գործել են, օրինակ. կաղապարի մարմին նմանատիպ դանդաղ հարցումներ կամ բուն հարցման տեքստը:

«Փաստերը» արդեն երկար ժամանակ բաժանվում էին օրեցօր, այնպես որ մենք հանգիստ ջնջեցինք հնացած բաժինները, և դրանք մեզ չէին անհանգստացնում (տեղեկամատյաններ): Բայց բառարանների խնդիր կար...

Չասեմ, որ դրանք շատ էին, բայց մոտավորապես 100 ՏԲ «փաստերի» արդյունքում ստացվեց 2.5 ՏԲ բառարան. Դուք չեք կարող հարմար կերպով որևէ բան ջնջել նման աղյուսակից, չեք կարող սեղմել այն համապատասխան ժամանակում, և դրան գրելը աստիճանաբար դանդաղեց:

Բառարանի պես... դրա մեջ յուրաքանչյուր գրառում պետք է ներկայացվի ուղիղ մեկ անգամ... և սա ճիշտ է, բայց... Ոչ ոք մեզ չի խանգարում ունենալ։ յուրաքանչյուր օրվա համար առանձին բառարան! Այո, սա բերում է որոշակի ավելորդություն, բայց թույլ է տալիս.

  • գրել/կարդալ ավելի արագ ավելի փոքր հատվածի պատճառով
  • սպառում է ավելի քիչ հիշողություն աշխատելով ավելի կոմպակտ ինդեքսների հետ
  • պահել ավելի քիչ տվյալներ հնացած արագ հեռացնելու ունակության շնորհիվ

Միջոցառումների ողջ համալիրի արդյունքում CPU-ի բեռնվածությունը նվազել է ~30%-ով, սկավառակի բեռնվածությունը ~50%-ով:

PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ
Միևնույն ժամանակ, մենք շարունակեցինք նույն բանը գրել տվյալների բազայում, պարզապես ավելի քիչ ծանրաբեռնվածությամբ:

#2. Տվյալների բազայի էվոլյուցիա և վերամշակում

Այսպիսով, մենք հաստատվեցինք մեր ունեցածի վրա ամեն օր ունի իր բաժինը տվյալների հետ։ Իրականում, CHECK (dt = '2018-10-12'::date) — և կա բաժանման ստեղն և պայման, որ գրառումը ընկնի կոնկրետ բաժին:

Քանի որ մեր ծառայության բոլոր հաշվետվությունները ստեղծվել են կոնկրետ ամսաթվի համատեքստում, «չբաժանված ժամանակներից» ի վեր դրանց ինդեքսները եղել են բոլոր տեսակի (Սերվեր, Ամսաթիվ, պլանի ձևանմուշ), (Սերվեր, Ամսաթիվ, պլանի հանգույց), (Ամսաթիվ, Սխալների դաս, Սերվեր)...

Բայց հիմա նրանք ապրում են ամեն հատվածում ձեր պատճենները յուրաքանչյուր այդպիսի ցուցանիշ... Եվ յուրաքանչյուր բաժնի շրջանակներում ամսաթիվը հաստատուն է... Ստացվում է, որ հիմա մենք յուրաքանչյուր նման ցուցանիշի մեջ ենք պարզապես մուտքագրեք հաստատուն որպես դաշտերից մեկը, որը մեծացնում է և՛ իր ծավալը, և՛ դրա որոնման ժամանակը, բայց ոչ մի արդյունքի չի բերում։ Փոցխը թողել են իրենց, օպ...

PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ
Օպտիմալացման ուղղությունը ակնհայտ է՝ պարզ հեռացնել ամսաթվի դաշտը բոլոր ինդեքսներից բաժանված սեղանների վրա: Հաշվի առնելով մեր ծավալները, շահույթը մոտ է 1 ՏԲ/շաբաթ!

Հիմա նկատենք, որ այս տերաբայթը դեռ պետք է ինչ-որ կերպ ձայնագրվեր։ Այսինքն՝ մենք նույնպես սկավառակն այժմ պետք է ավելի քիչ բեռնվի! Այս նկարում հստակ երևում է մաքրումից ստացված էֆեկտը, որին մենք մեկ շաբաթ ենք նվիրել.

PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ

#3. Պիկ բեռի «տարածում».

Բեռնված համակարգերի մեծ խնդիրներից մեկն այն է ավելորդ համաժամացման որոշ գործողություններ, որոնք դա չեն պահանջում: Երբեմն «որովհետև չէին նկատում», երբեմն «այդպես ավելի հեշտ էր», բայց վաղ թե ուշ պետք է ազատվել դրանից։

Եկեք մեծացնենք նախորդ նկարը և տեսնենք, որ մենք ունենք սկավառակ «պոմպեր» բեռի տակ կրկնակի ամպլիտուդով հարակից նմուշների միջև, ինչը ակնհայտորեն «վիճակագրորեն» չպետք է տեղի ունենա նման մի շարք գործողությունների դեպքում.

PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ

Սա բավականին հեշտ է հասնել: Մենք արդեն սկսել ենք մոնիտորինգը գրեթե 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 օր, 1 ՏԲ

Եվ սա պահեստավորման բեռի ուղեկցող անկումն է.

PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ

Ընդհանուր

«Տերաբայթ օրական» պարզապես սարսափելի է հնչում: Եթե ​​ամեն ինչ ճիշտ եք անում, ապա սա պարզապես 2^40 բայթ / 86400 վայրկյան = ~ 12.5 ՄԲ/վոր նույնիսկ աշխատասեղանի IDE պտուտակներ էին պահում: 🙂

Բայց եթե լուրջ, նույնիսկ օրվա ընթացքում բեռի տասնապատիկ «թեքվելով», դուք հեշտությամբ կարող եք բավարարել ժամանակակից SSD-ների հնարավորությունները:

PostgreSQL-ում գրում ենք ենթալույսի վրա՝ 1 հոսթ, 1 օր, 1 ՏԲ

Source: www.habr.com

Добавить комментарий