Առաջարկում եմ կարդալ Վլադիմիր Սիտնիկովի 2016 թվականի սկզբի զեկույցի սղագրությունը «PostgreSQL-ը և JDBC-ն քամում են ամբողջ հյութը»
Բարի օր Ես Վլադիմիր Սիտնիկովն եմ։ Ես աշխատում եմ NetCracker-ում արդեն 10 տարի: Եվ ես հիմնականում զբաղվում եմ արտադրողականությամբ: Java-ի հետ կապված ամեն ինչ, SQL-ի հետ կապված ամեն ինչ այն է, ինչ ես սիրում եմ:
Իսկ այսօր ես կխոսեմ այն մասին, թե ինչի հետ հանդիպեցինք ընկերությունում, երբ սկսեցինք օգտագործել PostgreSQL-ը որպես տվյալների բազայի սերվեր։ Իսկ մենք հիմնականում աշխատում ենք Java-ի հետ։ Բայց այն, ինչ ես ձեզ այսօր կպատմեմ, միայն Java-ի մասին չէ: Ինչպես ցույց է տվել պրակտիկան, դա տեղի է ունենում նաև այլ լեզուներով:
Մենք կխոսենք.
- տվյալների նմուշառման մասին։
- Տվյալների պահպանման մասին.
- Եվ նաև կատարման մասին:
- Իսկ այնտեղ թաղված ստորջրյա փոցխերի մասին։
Սկսենք մի պարզ հարցից. Աղյուսակից ընտրում ենք մեկ տող՝ հիմնվելով հիմնական բանալի վրա։
Տվյալների բազան գտնվում է նույն հոսթի վրա: Եվ այս ամբողջ գյուղատնտեսությունը տևում է 20 միլիվայրկյան:
Այս 20 միլիվայրկյանները շատ են: Եթե դուք ունեք 100 նման հարցումներ, ապա դուք վայրկյանում ժամանակ եք ծախսում այս հարցումները պտտելու համար, այսինքն՝ մենք ժամանակ ենք կորցնում:
Մենք չենք սիրում դա անել և տեսնենք, թե ինչ է մեզ առաջարկում բազան դրա համար: Տվյալների բազան մեզ առաջարկում է հարցումներ կատարելու երկու տարբերակ.
Առաջին տարբերակը պարզ խնդրանքն է: Ի՞նչ լավ բան կա դրա մեջ: Այն, որ վերցնում ենք ու ուղարկում, և ոչ ավելին։
Տվյալների բազան ունի նաև առաջադեմ հարցում, որն ավելի բարդ է, բայց ավելի ֆունկցիոնալ: Դուք կարող եք առանձին ուղարկել վերլուծության, կատարման, փոփոխական կապման հարցում և այլն:
Գեր ընդլայնված հարցումը մի բան է, որը մենք չենք անդրադառնա ընթացիկ զեկույցում: Մենք, երևի, ինչ-որ բան ենք ուզում տվյալների բազայից, և կա ցանկությունների ցուցակ, որը ձևավորվել է ինչ-որ ձևով, այսինքն՝ սա այն է, ինչ մենք ուզում ենք, բայց հիմա և հաջորդ տարի դա անհնար է։ Այսպիսով, մենք պարզապես ձայնագրեցինք այն և կշրջենք՝ ցնցելով հիմնական մարդկանց:
Եվ այն, ինչ մենք կարող ենք անել, պարզ հարցումն է և ընդլայնված հարցումը:
Ինչն է առանձնահատուկ յուրաքանչյուր մոտեցման մեջ:
Պարզ հարցումը լավ է մեկանգամյա կատարման համար: Մի անգամ արված և մոռացված: Եվ խնդիրն այն է, որ այն չի աջակցում երկուական տվյալների ձևաչափին, այսինքն՝ այն հարմար չէ բարձր արդյունավետության որոշ համակարգերի համար:
Ընդլայնված հարցում – թույլ է տալիս ժամանակ խնայել վերլուծության վրա: Սա այն է, ինչ մենք արեցինք և սկսեցինք օգտագործել: Սա իսկապես, իսկապես օգնեց մեզ: Խնայողություններ կան ոչ միայն վերլուծության վրա: Տվյալների փոխանցման խնայողություններ կան: Երկուական ձևաչափով տվյալների փոխանցումը շատ ավելի արդյունավետ է:
Անցնենք պրակտիկային։ Ահա թե ինչ տեսք ունի տիպիկ հավելվածը։ Դա կարող է լինել Java և այլն:
Մենք ստեղծել ենք հայտարարություն. Կատարեց հրամանը. Ստեղծվել է մոտ. Որտեղ է այստեղ սխալը: Ինչումն է խնդիրը? Ոչ մի խնդիր. Ահա թե ինչ է ասվում բոլոր գրքերում. Այսպես պետք է գրել. Եթե ցանկանում եք առավելագույն կատարողականություն, գրեք այսպես.
Բայց պրակտիկան ցույց է տվել, որ դա չի աշխատում: Ինչո՞ւ։ Քանի որ մենք ունենք «փակ» մեթոդ. Եվ երբ մենք դա անում ենք, տվյալների բազայի տեսանկյունից պարզվում է, որ դա նման է ծխողի, որն աշխատում է տվյալների բազայի հետ: Մենք ասացինք «PARSE EXECUTE DEALLOCATE»:
Ինչու՞ հայտարարությունների այս ավելորդ ստեղծումն ու բեռնաթափումը։ Դրանք ոչ մեկին պետք չեն։ Բայց այն, ինչ սովորաբար տեղի է ունենում PreparedStatements-ում, այն է, որ երբ մենք դրանք փակում ենք, նրանք փակում են տվյալների բազայի ամեն ինչ: Սա այն չէ, ինչ մենք ուզում ենք։
Մենք ցանկանում ենք, ինչպես առողջ մարդիկ, աշխատել բազայի հետ։ Մեկ անգամ վերցրել ու պատրաստել ենք մեր հայտարարությունը, հետո բազմիցս կատարում ենք։ Իրականում, շատ անգամ, սա մեկ անգամ է դիմումների ողջ կյանքում, դրանք վերլուծվել են: Եվ մենք օգտագործում ենք նույն հայտարարության id-ը տարբեր REST-ների վրա: Սա է մեր նպատակը։
Ինչպե՞ս կարող ենք դրան հասնել:
Դա շատ պարզ է՝ հայտարարությունները փակելու կարիք չկա: Մենք գրում ենք այսպես՝ «պատրաստել» «կատարել»։
Եթե մենք գործարկենք նման բան, ապա պարզ է, որ ինչ-որ բան ինչ-որ տեղ կհեղեղի: Եթե պարզ չէ, կարող եք փորձել: Եկեք գրենք չափանիշ, որն օգտագործում է այս պարզ մեթոդը: Ստեղծեք հայտարարություն. Մենք այն գործարկում ենք վարորդի ինչ-որ տարբերակի վրա և պարզում ենք, որ այն բավականին արագ խափանում է՝ կորցնելով ամբողջ հիշողությունը, որն ուներ:
Հասկանալի է, որ նման սխալները հեշտությամբ ուղղվում են։ Ես նրանց մասին չեմ խոսի։ Բայց ասեմ, որ նոր տարբերակը շատ ավելի արագ է աշխատում։ Մեթոդը հիմար է, բայց դեռ.
Ինչպե՞ս ճիշտ աշխատել: Ի՞նչ պետք է անենք դրա համար:
Իրականում դիմումները միշտ փակում են հայտարարությունները: Բոլոր գրքերում ասում են՝ փակիր, թե չէ հիշողությունը կթողնի։
Իսկ PostgreSQL-ը չգիտի՝ ինչպես քեշավորել հարցումները: Անհրաժեշտ է, որ յուրաքանչյուր նիստ իր համար ստեղծի այս քեշը:
Եվ մենք նույնպես չենք ուզում ժամանակ վատնել վերլուծության վրա:
Եվ ինչպես միշտ, մենք ունենք երկու տարբերակ.
Առաջին տարբերակն այն է, որ մենք վերցնում ենք այն և ասում, որ եկեք ամեն ինչ փաթաթենք PgSQL-ով: Այնտեղ կա քեշ։ Այն պահում է ամեն ինչ: Հիանալի կստացվի։ Մենք սա տեսանք։ Մենք ունենք 100500 հարցում։ Չի աշխատում. Մենք համաձայն չենք հարցումները ձեռքով ընթացակարգի վերածել: Ոչ ոչ.
Մենք ունենք երկրորդ տարբերակ՝ վերցրեք և ինքներս կտրեք։ Մենք բացում ենք աղբյուրները և սկսում կտրատել։ Տեսանք ու տեսանք։ Պարզվեց, որ դա այնքան էլ դժվար չէ անել։
Սա հայտնվեց 2015 թվականի օգոստոսին։ Այժմ կա ավելի ժամանակակից տարբերակ։ Եվ ամեն ինչ հիանալի է: Այն այնքան լավ է աշխատում, որ մենք ոչինչ չենք փոխում հավելվածում։ Եվ մենք նույնիսկ դադարեցինք մտածել PgSQL-ի ուղղությամբ, այսինքն՝ սա բավական էր, որպեսզի բոլոր վերադիր ծախսերը գրեթե զրոյի հասցնենք:
Համապատասխանաբար, սերվերի կողմից պատրաստված հայտարարություններն ակտիվանում են 5-րդ կատարման ժամանակ, որպեսզի խուսափեն տվյալների բազայում հիշողությունը վատնելուց յուրաքանչյուր մեկանգամյա հարցումով:
Կարող եք հարցնել՝ որտե՞ղ են թվերը: Ի՞նչ եք ստանում: Եվ այստեղ ես թվեր չեմ տա, քանի որ յուրաքանչյուր խնդրանք ունի իր սեփականը:
Մեր հարցումներն այնպիսին էին, որ մենք ծախսեցինք մոտ 20 միլիվայրկյան OLTP հարցումների վերլուծության վրա: Կատարման համար կար 0,5 միլիվայրկյան, վերլուծության համար՝ 20 միլիվայրկյան: Հարցում – 10 ԿԲ տեքստ, 170 տող պլան: Սա OLTP հարցում է: Այն պահանջում է 1, 5, 10 տող, երբեմն ավելի շատ:
Բայց մենք ընդհանրապես չէինք ուզում վատնել 20 միլիվայրկյան: Մենք այն իջեցրինք 0-ի։ Ամեն ինչ հիանալի է:
Ի՞նչ կարող ես վերցնել այստեղից: Եթե ունես Java, ուրեմն վերցնում ես դրայվերի ժամանակակից տարբերակը ու ուրախանում։
Եթե դուք խոսում եք այլ լեզվով, ապա մտածեք. գուցե սա ձեզ էլ է պետք: Որովհետև վերջնական լեզվի տեսանկյունից, օրինակ, եթե PL 8 կամ դուք ունեք LibPQ, ապա ձեզ համար ակնհայտ չէ, որ դուք ժամանակ եք ծախսում ոչ թե կատարման, վերլուծության վրա, և դա արժե ստուգել: Ինչպե՞ս: Ամեն ինչ անվճար է։
Միայն թե կան սխալներ և որոշ առանձնահատկություններ։ Եվ մենք նրանց մասին կխոսենք հենց հիմա: Դրա մեծ մասը կլինի արդյունաբերական հնագիտության մասին, այն մասին, թե ինչ գտանք, ինչի հանդիպեցինք:
Եթե հարցումը ստեղծվում է դինամիկ: Պատահում է. Ինչ-որ մեկը սոսնձում է տողերը, արդյունքում ստացվում է SQL հարցում:
Ինչու է նա վատը: Դա վատ է, քանի որ ամեն անգամ մենք հայտնվում ենք տարբեր լարերի հետ:
Եվ այս տարբեր տողի hashCode-ը պետք է նորից կարդալ: Սա իսկապես պրոցեսորի խնդիր է. երկար հարցման տեքստ գտնելն անգամ գոյություն ունեցող հեշում այնքան էլ հեշտ չէ: Հետևաբար, եզրակացությունը պարզ է՝ հարցումներ չառաջացնել: Պահպանեք դրանք մեկ փոփոխականի մեջ: Եվ ուրախացեք:
Հաջորդ խնդիրը. Տվյալների տեսակները կարևոր են: Կան ORM-ներ, որոնք ասում են, որ կարևոր չէ, թե ինչ տեսակի NULL կա, թող լինի մի տեսակ: Եթե Int, ապա մենք ասում ենք setInt: Իսկ եթե NULL, ապա թող միշտ լինի VARCHAR: Եվ ի՞նչ տարբերություն, ի վերջո, թե ինչ NULL կա: Տվյալների բազան ինքնին կհասկանա ամեն ինչ։ Եվ այս նկարը չի աշխատում:
Գործնականում տվյալների բազան ընդհանրապես չի հետաքրքրում: Եթե առաջին անգամ ասացիք, որ սա թիվ է, իսկ երկրորդ անգամ ասացիք, որ դա VARCHAR է, ապա անհնար է կրկին օգտագործել Սերվերի կողմից պատրաստված հայտարարությունները։ Եվ այս դեպքում մենք պետք է վերստեղծենք մեր հայտարարությունը։
Եթե դուք կատարում եք նույն հարցումը, համոզվեք, որ ձեր սյունակի տվյալների տեսակները շփոթված չեն: Դուք պետք է ուշադիր լինեք NULL-ի համար: Սա սովորական սխալ է, որը մենք ունեցել ենք PreparedStatements-ի օգտագործումից հետո
Լավ, միացված է: Երևի վարորդին են տարել։ Եվ արտադրողականությունը նվազել է: Գործերը վատացան:
Ինչպե՞ս է դա տեղի ունենում: Սա վրիպակ է, թե՞ հատկանիշ: Ցավոք, չհաջողվեց հասկանալ՝ սա վրիպակ է, թե հատկանիշ։ Բայց այս խնդիրը վերարտադրելու շատ պարզ սցենար կա. Նա բոլորովին անսպասելիորեն դարանակալեց մեզ։ Եվ այն բաղկացած է բառացիորեն մեկ աղյուսակից նմուշառումից։ Մենք, իհարկե, ավելի շատ նման խնդրանքներ ունեինք։ Որպես կանոն, նրանք ներառում էին երկու կամ երեք աղյուսակ, բայց կա նման նվագարկման սցենար: Վերցրեք ցանկացած տարբերակ ձեր տվյալների բազայից և խաղացեք այն:
Բանն այն է, որ մենք ունենք երկու սյունակ, որոնցից յուրաքանչյուրը ինդեքսավորված է։ Մեկ NULL սյունակում կա միլիոն տող: Իսկ երկրորդ սյունակը պարունակում է ընդամենը 20 տող։ Երբ մենք կատարում ենք առանց կապված փոփոխականների, ամեն ինչ լավ է աշխատում:
Եթե մենք սկսենք կատարել կապված փոփոխականներով, այսինքն՝ մենք կատարում ենք «?" կամ «$1» մեր խնդրանքի համար, ի՞նչ ենք մենք ստանում:
Առաջին մահապատիժը սպասվածի պես է. Երկրորդը մի փոքր ավելի արագ է։ Ինչ-որ բան պահվել է քեշում: Երրորդ, չորրորդ, հինգերորդ: Հետո պայթյուն - և նման մի բան: Իսկ ամենավատն այն է, որ դա տեղի է ունենում վեցերորդ մահապատժի ժամանակ։ Ո՞վ գիտեր, որ պետք է կատարել ուղիղ վեց մահապատիժ՝ հասկանալու համար, թե որն է իրականում կատարման ծրագիրը։
Ո՞վ է մեղավոր. Ինչ է պատահել? Տվյալների բազան պարունակում է օպտիմալացում: Եվ կարծես օպտիմիզացված է ընդհանուր գործի համար: Եվ, համապատասխանաբար, ինչ-որ պահից սկսած՝ նա անցնում է ընդհանուր պլանի, որը, ցավոք, կարող է տարբեր լինել։ Կարող է պարզվել, որ նույնն է, կամ կարող է տարբեր լինել: Եվ կա որոշակի շեմային արժեք, որը հանգեցնում է այս վարքագծին:
Ի՞նչ կարող ես անել դրա դեմ: Այստեղ, իհարկե, ավելի դժվար է ինչ-որ բան ենթադրել։ Կա մի պարզ լուծում, որը մենք օգտագործում ենք. Սա +0 է, OFFSET 0: Անշուշտ, դուք գիտեք նման լուծումներ: Մենք պարզապես վերցնում ենք այն և ավելացնում «+0» հարցումին, և ամեն ինչ լավ է: Ես ձեզ ավելի ուշ ցույց կտամ:
Եվ կա ևս մեկ տարբերակ՝ ավելի ուշադիր նայեք պլաններին։ Մշակողը պետք է ոչ միայն հարցում գրի, այլև 6 անգամ ասի «բացատրել վերլուծել»։ Եթե 5 լինի, չի աշխատի:
Եվ կա երրորդ տարբերակ՝ նամակ գրել pgsql-hackers-ին։ Գրեցի, սակայն, դեռ պարզ չէ՝ սա վրիպակ է, թե ֆունկցիա։
Մինչ մենք մտածում ենք՝ սա վրիպակ է, թե ֆունկցիա, եկեք շտկենք այն: Եկեք ընդունենք մեր խնդրանքը և ավելացնենք «+0»: Ամեն ինչ լավ է. Երկու խորհրդանիշ, և դուք նույնիսկ պետք չէ մտածել, թե ինչպես է այն կամ ինչ է դա: Շատ պարզ. Մենք պարզապես արգելեցինք տվյալների բազան օգտագործել ինդեքս այս սյունակում: Մենք չունենք ինդեքս «+0» սյունակում և վերջ, տվյալների բազան չի օգտագործում ինդեքսը, ամեն ինչ լավ է:
Սա 6 բացատրության կանոնն է: Այժմ ընթացիկ տարբերակներում դուք պետք է դա անեք 6 անգամ, եթե ունեք կապված փոփոխականներ: Եթե դուք չունեք կապված փոփոխականներ, սա այն է, ինչ մենք անում ենք: Եվ վերջում հենց այս խնդրանքն է ձախողվում։ Դա բարդ բան չէ:
Թվում է, թե որքան հնարավոր է: Սխալ՝ այստեղ, վրիպակ՝ այնտեղ։ Իրականում, սխալն ամենուր է:
Եկեք ավելի սերտ նայենք: Օրինակ, մենք ունենք երկու սխեմա. A սխեման S աղյուսակով և B դիագրամ S աղյուսակով: Հարցում – ընտրեք տվյալները աղյուսակից: Ի՞նչ կունենանք այս դեպքում։ Սխալ կունենանք. Մենք կունենանք վերը նշված բոլորը: Կանոնն է՝ ամենուր վրիպակ կա, մենք կունենանք վերը նշված բոլորը:
Այժմ հարցն այն է. «Ինչո՞ւ»: Թվում է, թե կա փաստաթուղթ, որ եթե մենք ունենք սխեմա, ապա կա «search_path» փոփոխական, որը մեզ ասում է, թե որտեղ փնտրել աղյուսակը: Թվում է, թե փոփոխական կա.
Ինչումն է խնդիրը? Խնդիրն այն է, որ սերվերի կողմից պատրաստված հայտարարությունները չեն կասկածում, որ search_path-ը կարող է փոխվել ինչ-որ մեկի կողմից: Այս արժեքը, կարծես, մնում է անփոփոխ տվյալների բազայի համար: Եվ որոշ մասեր կարող են նոր իմաստներ չստանալ:
Իհարկե, դա կախված է այն տարբերակից, որը դուք փորձարկում եք: Կախված է նրանից, թե որքանով են տարբերվում ձեր սեղանները: Իսկ 9.1 տարբերակը պարզապես կկատարի հին հարցումները: Նոր տարբերակները կարող են բռնել վրիպակը և ասել, որ դուք սխալ ունեք:
Ինչպե՞ս բուժել այն: Կա մի պարզ բաղադրատոմս՝ մի արեք դա։ Երբ հավելվածն աշխատում է, կարիք չկա փոխել search_path-ը: Եթե փոխեք, ավելի լավ է նոր կապ ստեղծել։
Դուք կարող եք քննարկել, այսինքն բացել, քննարկել, ավելացնել: Միգուցե մենք կարողանանք համոզել տվյալների բազայի մշակողներին, որ երբ ինչ-որ մեկը փոխում է արժեքը, տվյալների բազան պետք է հաճախորդին ասի այս մասին. «Տեսեք, ձեր արժեքը թարմացվել է այստեղ: Միգուցե պետք է զրոյացնել հայտարարությունները և վերստեղծե՞լ դրանք»։ Հիմա տվյալների բազան իրեն գաղտնի է պահում և ոչ մի կերպ չի հայտնում, որ ներսում ինչ-որ տեղ փոխվել են հայտարարությունները։
Եվ նորից շեշտեմ՝ սա Java-ին բնորոշ մի բան է։ Մենք նույն բանը կտեսնենք PL/pgSQL-ում մեկ առ մեկ: Բայց այնտեղ կվերարտադրվի։
Փորձենք ավելի շատ տվյալների ընտրություն: Մենք ընտրում ենք և ընտրում։ Մենք ունենք մեկ միլիոն տող ունեցող աղյուսակ: Յուրաքանչյուր տող մեկ կիլոբայթ է: Մոտավորապես մեկ գիգաբայթ տվյալներ: Իսկ Java մեքենայում մենք ունենք 128 մեգաբայթանոց աշխատանքային հիշողություն։
Մենք, ինչպես խորհուրդ է տրվում բոլոր գրքերում, օգտագործում ենք հոսքային մշակում: Այսինքն՝ բացում ենք resultSet-ը ու այնտեղից կամաց-կամաց կարդում ենք տվյալները։ Արդյո՞ք դա կաշխատի: Կընկնի հիշողությունից? Մի քիչ կկարդա՞ք։ Եկեք վստահենք տվյալների բազային, եկեք վստահենք Postgres-ին: Մենք դրան չենք հավատում: Մենք դուրս կգա՞նք հիշողությունից: Ո՞վ է զգացել OutOfMemory-ը: Ո՞վ կարողացավ դրանից հետո շտկել։ Ինչ-որ մեկին հաջողվեց շտկել:
Եթե դուք ունեք մեկ միլիոն տող, դուք չեք կարող պարզապես ընտրել և ընտրել: Պահանջվում է OFFSET/LIMIT: Ո՞վ է կողմ այս տարբերակին: Իսկ ո՞վ է կողմ autoCommit-ով խաղալուն։
Այստեղ, ինչպես միշտ, ամենաանսպասելի տարբերակը ճիշտ է ստացվում։ Իսկ եթե հանկարծ անջատեք autoCommit-ը, դա կօգնի։ Ինչո՞ւ է այդպես։ Գիտությունը չգիտի այս մասին։
Բայց լռելյայնորեն, բոլոր հաճախորդները, որոնք միանում են Postgres տվյալների բազային, վերցնում են ամբողջ տվյալները: PgJDBC-ն այս առումով բացառություն չէ, այն ընտրում է բոլոր տողերը:
Կա FetchSize թեմայի փոփոխություն, այսինքն՝ դուք կարող եք առանձին հայտարարության մակարդակով ասել, որ այստեղ խնդրում ենք ընտրել տվյալները 10, 50-ով: Բայց սա չի աշխատում, քանի դեռ չեք անջատել autoCommit-ը: Անջատված է autoCommit - այն սկսում է աշխատել:
Բայց կոդի միջով անցնելը և ամենուր setFetchSize սահմանելը անհարմար է: Հետևաբար, մենք կատարել ենք կարգավորում, որը կասի լռելյայն արժեքը ամբողջ կապի համար:
Այդպես էլ ասացինք։ Պարամետրը կարգավորվել է: Իսկ ի՞նչ ստացանք։ Եթե մենք ընտրում ենք փոքր գումարներ, եթե, օրինակ, ընտրում ենք 10 տող միաժամանակ, ապա ունենք շատ մեծ վերադիր ծախսեր։ Հետեւաբար, այս արժեքը պետք է սահմանվի մոտ հարյուր:
Իդեալում, իհարկե, դուք դեռ պետք է սովորեք, թե ինչպես սահմանափակել այն բայթերով, բայց բաղադրատոմսը հետևյալն է. defaultRowFetchSize սահմանեք հարյուրից ավելի և երջանիկ եղեք:
Անցնենք տվյալների տեղադրմանը։ Տեղադրումն ավելի հեշտ է, կան տարբեր տարբերակներ: Օրինակ՝ INSERT, VALUES: Սա լավ տարբերակ է։ Դուք կարող եք ասել «INSERT SELECT»: Գործնականում նույն բանն է. Կատարման մեջ տարբերություն չկա։
Գրքերն ասում են, որ դուք պետք է կատարեք Batch հայտարարություն, գրքերում ասվում է, որ դուք կարող եք ավելի բարդ հրամաններ կատարել մի քանի փակագծերով: Իսկ Postgres-ն ունի մի հրաշալի հատկություն՝ դուք կարող եք COPY անել, այսինքն՝ ավելի արագ:
Եթե չափեք այն, կարող եք կրկին մի քանի հետաքրքիր բացահայտումներ անել: Ինչպե՞ս ենք մենք ուզում, որ սա աշխատի: Մենք ցանկանում ենք չվերլուծել և չկատարել ավելորդ հրամանները:
Գործնականում TCP-ն մեզ թույլ չի տալիս դա անել: Եթե հաճախորդը զբաղված է հարցում ուղարկելով, ապա տվյալների բազան չի կարդում հարցումները՝ փորձելով մեզ պատասխաններ ուղարկել: Վերջնական արդյունքն այն է, որ հաճախորդը սպասում է, որ տվյալների բազան կարդա հարցումը, իսկ տվյալների բազան սպասում է, որ հաճախորդը կարդա պատասխանը:
Եվ հետևաբար հաճախորդը ստիպված է լինում պարբերաբար ուղարկել համաժամացման փաթեթ: Լրացուցիչ ցանցային փոխազդեցություններ, լրացուցիչ ժամանակի վատնում:
Եվ որքան շատ ենք դրանք ավելացնում, այնքան վատանում է: Վարորդը բավականին հոռետես է և դրանք ավելացնում է բավականին հաճախ՝ մոտավորապես 200 տողում մեկ անգամ՝ կախված գծերի չափից և այլն։
Պատահում է, որ դուք ուղղում եք ընդամենը մեկ տող, և ամեն ինչ կարագանա 10 անգամ։ Պատահում է. Ինչո՞ւ։ Ինչպես միշտ, նման հաստատուն ինչ-որ տեղ արդեն օգտագործվել է։ Իսկ «128» արժեքը նշանակում էր չօգտագործել խմբաքանակ:
Լավ է, որ սա չի ներառվել պաշտոնական տարբերակում։ Հայտնաբերվել է մինչև թողարկման սկսվելը: Իմ տված բոլոր իմաստները հիմնված են ժամանակակից տարբերակների վրա։
Եկեք փորձենք այն: Մենք չափում ենք InsertBatch-ը պարզ: Մենք չափում ենք InsertBatch-ը մի քանի անգամ, այսինքն՝ նույն բանը, բայց շատ արժեքներ կան: Բարդ քայլ. Ոչ բոլորը կարող են դա անել, բայց դա այնքան պարզ քայլ է, որը շատ ավելի հեշտ է, քան COPY-ը:
Դուք կարող եք կատարել COPY:
Եվ դուք կարող եք դա անել կառույցների վրա: Հայտարարել Օգտատիրոջ լռելյայն տեսակը, փոխանցել զանգվածը և INSERT ուղղակիորեն աղյուսակում:
Եթե բացեք հղումը՝ pgjdbc/ubenchmsrk/InsertBatch.java, ապա այս կոդը գտնվում է GitHub-ում: Դուք կարող եք տեսնել, թե կոնկրետ ինչ հարցումներ են ստեղծվում այնտեղ: Կարեւոր չէ։
Մենք մեկնարկեցինք. Եվ առաջին բանը, որ մենք հասկացանք, այն էր, որ խմբաքանակ չօգտագործելը պարզապես անհնար է: Փաթեթավորման բոլոր տարբերակները զրո են, այսինքն՝ կատարման ժամանակը գործնականում զրոյական է մեկանգամյա կատարման համեմատ:
Մենք տեղադրում ենք տվյալներ. Շատ պարզ սեղան է։ Երեք սյունակ. Իսկ ի՞նչ ենք մենք տեսնում այստեղ։ Մենք տեսնում ենք, որ այս երեք տարբերակներն էլ մոտավորապես համեմատելի են: Իսկ COPY-ն, իհարկե, ավելի լավն է:
Սա այն դեպքում, երբ մենք տեղադրում ենք կտորներ: Երբ ասում էինք, որ մեկ VALUES արժեք, երկու VALUES արժեք, երեք VALUES արժեք, կամ նշում էինք դրանցից 10-ը՝ բաժանված ստորակետով: Սա հիմա ուղղակի հորիզոնական է: 1, 2, 4, 128. Երևում է, որ խմբաքանակի ներդիրը, որը գծված է կապույտ գույնով, նրան շատ ավելի լավ է զգում։ Այսինքն, երբ մեկ-մեկ տեղադրում ես կամ նույնիսկ չորսը միաժամանակ դնում ես, այն կրկնակի լավ է դառնում, պարզապես այն պատճառով, որ մենք մի փոքր ավելի խցկվել ենք ԱՐԺԵՔՆԵՐԻ մեջ: Ավելի քիչ EXECUTE գործողություններ:
COPY-ի օգտագործումը փոքր ծավալների վրա չափազանց անհեռանկարային է: Ես նույնիսկ առաջին երկուսի վրա չեմ նկարել: Նրանք գնում են դրախտ, այսինքն՝ այս կանաչ թվերը COPY-ի համար։
COPY-ը պետք է օգտագործվի, երբ դուք ունեք առնվազն հարյուր տող տվյալներ: Այս կապի բացման ծախսը մեծ է: Եվ, ճիշտն ասած, ես չեմ փորել այս ուղղությամբ: Ես օպտիմիզացրել եմ Batch-ը, բայց ոչ COPY:
Ի՞նչ անենք հետո: Մենք փորձեցինք այն: Մենք հասկանում ենք, որ մենք պետք է օգտագործենք կամ կառուցվածքներ, կամ խելացի բաղնիք, որը միավորում է մի քանի իմաստներ:
Ի՞նչ պետք է վերցնեք այսօրվա զեկույցից:
- PreparedStatement-ը մեր ամեն ինչն է: Սա շատ բան է տալիս արտադրողականության համար: Այն առաջացնում է քսուքի մեծ փխրունություն:
- Եվ դուք պետք է 6 անգամ կատարեք EXPLAIN ANALYZE:
- Եվ մենք պետք է նոսրացնենք OFFSET 0-ը և հնարքները, ինչպիսիք են +0-ը, որպեսզի շտկենք մեր խնդրահարույց հարցումների մնացած տոկոսը:
Source: www.habr.com