PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Men sizga Vladimir Sitnikovning 2016 yil boshida "PostgreSQL va JDBC barcha sharbatni siqib chiqarmoqda" hisobotining stenogrammasini o'qishni taklif qilaman.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Hayrli kun! Mening ismim Vladimir Sitnikov. Men NetCracker-da 10 yildan beri ishlayman. Men esa asosan mahsuldorlikka qiziqaman. Java bilan bog'liq hamma narsa, SQL bilan bog'liq hamma narsa menga yoqadi.

Va bugun men PostgreSQL-dan ma'lumotlar bazasi serveri sifatida foydalanishni boshlaganimizda kompaniyada nimalarga duch kelganimiz haqida gapiraman. Va biz asosan Java bilan ishlaymiz. Lekin bugun sizga aytmoqchi bo'lgan narsam faqat Java haqida emas. Amaliyot shuni ko'rsatadiki, bu boshqa tillarda ham uchraydi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Biz gaplashamiz:

  • ma'lumotlar namunasi haqida.
  • Ma'lumotlarni saqlash haqida.
  • Va shuningdek, ishlash haqida.
  • Va u erda ko'milgan suv osti tırmıklar haqida.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Keling, oddiy savol bilan boshlaylik. Birlamchi kalit asosida jadvaldan bitta qatorni tanlaymiz.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Ma'lumotlar bazasi bir xil xostda joylashgan. Va bu dehqonchilikning barchasi 20 millisekundni oladi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Bu 20 millisekundlar juda ko'p. Agar sizda 100 ta shunday so'rovlar bo'lsa, siz bu so'rovlar bo'ylab harakatlanish uchun soniyasiga vaqt sarflaysiz, ya'ni biz vaqtni behuda sarflaymiz.

Biz buni qilishni yoqtirmaymiz va baza buning uchun bizga nimani taklif qilishini ko'rib chiqamiz. Ma'lumotlar bazasi bizga so'rovlarni bajarish uchun ikkita variantni taklif qiladi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Birinchi variant - oddiy so'rov. Buning nimasi yaxshi? Biz uni olib yuborishimiz va boshqa hech narsa emas.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

https://github.com/pgjdbc/pgjdbc/pull/478

Ma'lumotlar bazasida murakkabroq, ammo funktsionalroq bo'lgan rivojlangan so'rov ham mavjud. Siz so'rovni tahlil qilish, bajarish, o'zgaruvchan bog'lash va boshqalar uchun alohida yuborishingiz mumkin.

Super kengaytirilgan so'rov biz joriy hisobotda ko'rib chiqmaydigan narsadir. Biz, ehtimol, ma'lumotlar bazasidan biror narsani xohlaymiz va u erda qandaydir shaklda shakllangan istaklar ro'yxati mavjud, ya'ni bu biz xohlagan narsa, lekin hozir va keyingi yilda bu mumkin emas. Shunday qilib, biz uni yozib oldik va biz asosiy odamlarni silkitamiz.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Va biz qila oladigan narsa oddiy so'rov va kengaytirilgan so'rovdir.

Har bir yondashuvning o'ziga xos xususiyati nimada?

Oddiy so'rov bir martalik bajarish uchun yaxshi. Bir marta bajarilgan va unutilgan. Va muammo shundaki, u ikkilik ma'lumotlar formatini qo'llab-quvvatlamaydi, ya'ni ba'zi yuqori samarali tizimlar uchun mos emas.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Kengaytirilgan so'rov - tahlil qilish vaqtini tejash imkonini beradi. Biz buni qildik va foydalanishni boshladik. Bu bizga haqiqatan ham yordam berdi. Tahlil qilishda nafaqat tejamkorlik mavjud. Ma'lumot uzatishda tejamkorlik mavjud. Ikkilik formatda ma'lumotlarni uzatish ancha samarali.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Keling, amaliyotga o'tamiz. Oddiy dastur shunday ko'rinadi. Bu Java va boshqalar bo'lishi mumkin.

Biz bayonot yaratdik. Buyruqni bajardi. Yaqin yaratilgan. Bu yerda xato qayerda? Muammo nimada? Muammo yo'q. Bu barcha kitoblarda aytilgan. Bu shunday yozilishi kerak. Maksimal ishlashni istasangiz, shunday yozing.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Ammo amaliyot shuni ko'rsatdiki, bu ishlamaydi. Nega? Chunki bizda “yaqin” usuli bor. Va biz buni qilganimizda, ma'lumotlar bazasi nuqtai nazaridan, bu ma'lumotlar bazasi bilan ishlaydigan chekuvchiga o'xshaydi. Biz "PARSE EXECUTE DEALLOCATE" ni aytdik.

Nega bu qo'shimcha bayonotlarni yaratish va tushirish? Ular hech kimga kerak emas. Ammo odatda PreparedStatements-da sodir bo'ladigan narsa shundaki, biz ularni yopganimizda, ular ma'lumotlar bazasidagi hamma narsani yopadilar. Bu biz xohlagan narsa emas.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Biz, sog'lom odamlar kabi, baza bilan ishlashni xohlaymiz. Biz bayonotimizni bir marta olib, tayyorladik, keyin ko'p marta bajardik. Aslida, ko'p marta - bu ilovalarning butun hayotida bir marta - ular tahlil qilingan. Va biz turli xil RESTlarda bir xil bayonot identifikatoridan foydalanamiz. Bu bizning maqsadimiz.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Bunga qanday erishishimiz mumkin?

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Bu juda oddiy - bayonotlarni yopish shart emas. Biz buni shunday yozamiz: "tayyorlash" "bajarish".

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Agar biz shunga o'xshash narsani ishga tushirsak, unda biror narsa to'lib ketishi aniq. Agar u aniq bo'lmasa, uni sinab ko'rishingiz mumkin. Keling, ushbu oddiy usuldan foydalanadigan benchmark yozamiz. Bayonot yarating. Biz uni drayverning ba'zi versiyasida ishga tushiramiz va u mavjud bo'lgan barcha xotirani yo'qotish bilan juda tez ishdan chiqishini aniqlaymiz.

Bunday xatolar osongina tuzatilishi aniq. Men ular haqida gapirmayman. Ammo shuni aytamanki, yangi versiya ancha tezroq ishlaydi. Usul ahmoq, ammo baribir.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Qanday qilib to'g'ri ishlash kerak? Buning uchun nima qilishimiz kerak?

Aslida, ilovalar har doim bayonotlarni yopadi. Hamma kitoblarda uni yoping, aks holda xotira oqadi, deyishadi.

Va PostgreSQL so'rovlarni keshlashni bilmaydi. Har bir seans ushbu keshni o'zi uchun yaratishi kerak.

Va biz ham tahlil qilish uchun vaqt sarflashni xohlamaymiz.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Va odatdagidek bizda ikkita variant bor.

Birinchi variant - biz uni qabul qilamiz va hamma narsani PgSQL-ga o'rab olamiz, deymiz. U erda kesh bor. U hamma narsani keshlaydi. Bu ajoyib chiqadi. Biz buni ko'rdik. Bizda 100500 ta so'rov bor. Ishlamayapti. Biz so'rovlarni qo'lda tartiblarga aylantirishga rozi emasmiz. Yoq yoq.

Bizda ikkinchi variant bor - uni oling va o'zimiz kesib oling. Biz manbalarni ochamiz va kesishni boshlaymiz. Biz ko'rdik va ko'rdik. Buni qilish unchalik qiyin emasligi ma'lum bo'ldi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

https://github.com/pgjdbc/pgjdbc/pull/319

Bu 2015 yil avgust oyida paydo bo'ldi. Endi yanada zamonaviy versiya mavjud. Va hamma narsa ajoyib. U shunchalik yaxshi ishlaydiki, biz ilovada hech narsani o'zgartirmaymiz. Va biz hatto PgSQL yo'nalishi bo'yicha o'ylashni to'xtatdik, ya'ni bu barcha umumiy xarajatlarni deyarli nolga tushirish uchun etarli edi.

Shunga ko'ra, har bir bir martalik so'rov bo'yicha ma'lumotlar bazasida xotirani behuda sarflamaslik uchun Server tomonidan tayyorlangan bayonotlar 5-ishlashda faollashtiriladi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Siz so'rashingiz mumkin - raqamlar qayerda? Nima olasiz? Va bu erda men raqamlarni bermayman, chunki har bir so'rovning o'ziga xosligi bor.

Bizning so'rovlarimiz shunday ediki, biz OLTP so'rovlarini tahlil qilish uchun taxminan 20 millisekund vaqt sarfladik. Amalga oshirish uchun 0,5 millisekund, tahlil qilish uchun 20 millisekund bor edi. So'rov - 10 KiB matn, 170 satr reja. Bu OLTP so'rovidir. U 1, 5, 10 qatorlarni, ba'zan esa ko'proq so'raydi.

Lekin biz 20 millisekundni umuman behuda sarflashni xohlamadik. Biz uni 0 ga tushirdik. Hammasi zo'r.

Bu yerdan nimani olib ketishingiz mumkin? Agar sizda Java bo'lsa, unda siz drayverning zamonaviy versiyasini olasiz va quvonasiz.

Agar siz boshqa tilda gapirsangiz, o'ylab ko'ring - ehtimol sizga bu kerakmi? Chunki oxirgi til nuqtai nazaridan, masalan, PL 8 yoki sizda LibPQ bo'lsa, unda siz ijroga emas, tahlil qilishga vaqt sarflayotganingiz aniq emas va buni tekshirishga arziydi. Qanaqasiga? Hammasi bepul.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Bundan tashqari, xatolar va ba'zi o'ziga xosliklar mavjud. Va biz hozir ular haqida gaplashamiz. Uning ko'p qismi sanoat arxeologiyasi, biz topgan narsalar, biz duch kelgan narsalar haqida bo'ladi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Agar so'rov dinamik ravishda yaratilgan bo'lsa. Bo'lib turadi. Kimdir satrlarni bir-biriga yopishtiradi, natijada SQL so'rovi paydo bo'ladi.

Nega u yomon? Bu yomon, chunki har safar biz boshqa satr bilan yakunlanamiz.

Va bu turli satrning hashCode qayta o'qilishi kerak. Bu haqiqatan ham CPU vazifasi - hatto mavjud xeshda ham uzoq so'rov matnini topish unchalik oson emas. Shuning uchun, xulosa oddiy - so'rovlarni yaratmang. Ularni bitta o'zgaruvchida saqlang. Va xursand bo'ling.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Keyingi muammo. Ma'lumotlar turlari muhim ahamiyatga ega. ORMlar bor, ular qanday NULL borligi muhim emas, qandaydir bo'lsin. Agar Int bo'lsa, biz setInt deymiz. Va agar NULL bo'lsa, u har doim VARCHAR bo'lsin. Va oxirida nima farqi bor NULL nima? Ma'lumotlar bazasining o'zi hamma narsani tushunadi. Va bu rasm ishlamaydi.

Amalda, ma'lumotlar bazasi umuman ahamiyat bermaydi. Agar siz birinchi marta bu raqam ekanligini aytgan bo'lsangiz va ikkinchi marta bu VARCHAR deb aytgan bo'lsangiz, Server tomonidan tayyorlangan bayonotlarni qayta ishlatish mumkin emas. Va bu holatda, biz bayonotimizni qayta yaratishimiz kerak.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Agar siz bir xil so'rovni bajarayotgan bo'lsangiz, ustuningizdagi ma'lumotlar turlari chalkashmasligiga ishonch hosil qiling. NULL ga e'tibor berishingiz kerak. Bu biz PreparedStatements-dan foydalanishni boshlaganimizdan keyin uchraydigan keng tarqalgan xatodir

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

OK, yoqilgan. Ehtimol, ular haydovchini olib ketishgan. Va hosildorlik pasaydi. Ishlar yomonlashdi.

Bu qanday sodir bo'ladi? Bu xato yoki xususiyatmi? Afsuski, bu xato yoki xususiyat ekanligini tushunishning iloji bo'lmadi. Ammo bu muammoni takrorlash uchun juda oddiy stsenariy mavjud. U kutilmaganda bizni pistirmaga oldi. Va u tom ma'noda bitta jadvaldan namuna olishdan iborat. Bizda, albatta, bunday iltimoslar ko'proq bo'lgan. Qoida tariqasida, ular ikkita yoki uchta jadvalni o'z ichiga oladi, ammo bunday ijro etish stsenariysi mavjud. Ma'lumotlar bazasidan istalgan versiyani oling va uni o'ynang.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

https://gist.github.com/vlsi/df08cbef370b2e86a5c1

Gap shundaki, bizda ikkita ustun bor, ularning har biri indekslanadi. Bitta NULL ustunda million qator mavjud. Ikkinchi ustunda esa atigi 20 ta satr mavjud. Agar biz chegaralangan o'zgaruvchilarsiz bajarsak, hamma narsa yaxshi ishlaydi.

Agar biz bog'langan o'zgaruvchilar bilan bajarishni boshlasak, ya'ni "?" yoki so'rovimiz uchun "$1", biz nimaga erishamiz?

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

https://gist.github.com/vlsi/df08cbef370b2e86a5c1

Birinchi ijro kutilganidek. Ikkinchisi biroz tezroq. Nimadir keshlangan. Uchinchi, to'rtinchi, beshinchi. Keyin portlash - va shunga o'xshash narsa. Va eng yomoni, bu oltinchi qatl paytida sodir bo'ladi. Haqiqiy ijro rejasi nima ekanligini tushunish uchun oltita qatl qilish kerakligini kim bilardi?

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Kim aybdor? Nima sodir bo `LDI? Ma'lumotlar bazasi optimallashtirishni o'z ichiga oladi. Va u umumiy holat uchun optimallashtirilgan ko'rinadi. Va shunga ko'ra, bir nuqtadan boshlab, u umumiy rejaga o'tadi, afsuski, boshqacha bo'lishi mumkin. Bu bir xil bo'lishi mumkin yoki boshqacha bo'lishi mumkin. Va bu xatti-harakatga olib keladigan qandaydir chegara qiymati mavjud.

Bu haqda nima qila olasiz? Bu erda, albatta, biror narsani taxmin qilish qiyinroq. Biz foydalanadigan oddiy yechim bor. Bu +0, OFFSET 0. Siz bunday echimlarni bilasiz. Biz uni qabul qilamiz va so'rovga "+0" qo'shamiz va hamma narsa yaxshi. Keyinroq ko'rsataman.

Va yana bir variant bor - rejalarni diqqat bilan ko'rib chiqing. Ishlab chiquvchi nafaqat so'rov yozishi, balki 6 marta "tahlil qilishni tushuntirish" deyishi kerak. Agar 5 bo'lsa, u ishlamaydi.

Va uchinchi variant bor - pgsql-xakerlarga xat yozing. Men yozdim, ammo bu xato yoki xususiyatmi, hali aniq emas.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

https://gist.github.com/vlsi/df08cbef370b2e86a5c1

Bu xato yoki xususiyatmi deb o'ylayotganimizda, keling, uni tuzatamiz. Keling, so'rovimizni olib, "+0" qo'shamiz. Hammasi yaxshi. Ikkita ramz va siz uning qanday yoki nima ekanligini o'ylashingiz shart emas. Juda oddiy. Biz shunchaki ma'lumotlar bazasiga ushbu ustundagi indeksdan foydalanishni taqiqladik. Bizda "+0" ustunida indeks yo'q va tamom, ma'lumotlar bazasi indeksdan foydalanmaydi, hamma narsa yaxshi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Bu 6 ta qoidani tushuntiradi. Endi joriy versiyalarda, agar sizda o'zgaruvchilar bog'langan bo'lsa, buni 6 marta bajarishingiz kerak. Agar sizda bog'langan o'zgaruvchilar bo'lmasa, biz shunday qilamiz. Va nihoyat, aynan shu so'rov muvaffaqiyatsizlikka uchraydi. Bu qiyin narsa emas.

Ko'rinib turibdiki, qanchalik mumkin? Bu yerda xato, u yerda xato. Aslida, xato hamma joyda.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Keling, batafsil ko'rib chiqaylik. Masalan, bizda ikkita sxema mavjud. S jadval bilan A sxemasi va S jadval bilan B diagrammasi. So'rov - jadvaldan ma'lumotlarni tanlash. Bu holatda bizda nima bo'ladi? Bizda xato bo'ladi. Biz yuqorida aytilganlarning barchasiga ega bo'lamiz. Qoida - xato hamma joyda, biz yuqorida aytilganlarning barchasiga ega bo'lamiz.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Endi savol: "Nima uchun?" Agar bizda sxema bo'lsa, unda jadvalni qayerdan izlash kerakligini ko'rsatadigan "search_path" o'zgaruvchisi mavjudligi haqida hujjatlar mavjud. O'zgaruvchi borga o'xshaydi.

Muammo nimada? Muammo shundaki, server tomonidan tayyorlangan bayonotlar qidiruv_yo'lini kimdir o'zgartirishi mumkinligiga shubha qilmaydi. Ushbu qiymat ma'lumotlar bazasi uchun doimiy bo'lib qoladi. Va ba'zi qismlar yangi ma'nolarni olmasligi mumkin.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Albatta, bu siz sinab ko'rayotgan versiyaga bog'liq. Jadvallaringiz qanchalik jiddiy farq qilishiga bog'liq. Va 9.1 versiyasi eski so'rovlarni oddiygina bajaradi. Yangi versiyalar xatoni aniqlashi va sizda xatolik borligini aytishi mumkin.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Search_path + server tomonidan tayyorlangan bayonotlarni o'rnating =
keshlangan reja natija turini o'zgartirmasligi kerak

Qanday davolash kerak? Oddiy retsepti bor - buni qilmang. Ilova ishlayotgan vaqtda search_path oʻzgartirishga hojat yoʻq. Agar siz o'zgartirsangiz, yangi ulanishni yaratish yaxshiroqdir.

Siz muhokama qilishingiz mumkin, ya'ni ochish, muhokama qilish, qo'shish. Ehtimol, biz ma'lumotlar bazasini ishlab chiquvchilarni kimdir qiymatni o'zgartirganda, ma'lumotlar bazasi mijozga bu haqda aytishi kerakligiga ishontirishimiz mumkin: "Mana, sizning qiymatingiz bu erda yangilangan. Balki siz bayonotlarni qayta o'rnatishingiz va ularni qayta yaratishingiz kerakdir? ” Endi ma'lumotlar bazasi yashirincha harakat qiladi va hech qanday tarzda bayonotlar ichida biron bir joyda o'zgarganligi haqida xabar bermaydi.

Va yana bir bor ta'kidlayman - bu Java uchun xos bo'lmagan narsa. Xuddi shu narsani PL/pgSQL da birma-bir ko'ramiz. Ammo u erda qayta ishlab chiqariladi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Keling, biroz ko'proq ma'lumot tanlashga harakat qilaylik. Biz tanlaymiz va tanlaymiz. Bizda million qatorli jadval bor. Har bir qator bir kilobayt. Taxminan bir gigabayt ma'lumot. Va bizda 128 megabaytlik Java mashinasida ishlaydigan xotira mavjud.

Biz, barcha kitoblarda tavsiya etilganidek, oqimlarni qayta ishlashdan foydalanamiz. Ya'ni, biz resultsSet-ni ochamiz va u yerdan ma'lumotlarni asta-sekin o'qiymiz. Bu ishlaydimi? Xotiradan tushib qoladimi? Bir oz o'qiysizmi? Keling, ma'lumotlar bazasiga ishonaylik, Postgresga ishonaylik. Biz bunga ishonmaymiz. Biz OutOFMemorydan tushib qolamizmi? OutOfMemory-ni kim boshdan kechirdi? Undan keyin kim uni tuzatishga muvaffaq bo'ldi? Kimdir uni tuzatishga muvaffaq bo'ldi.

Agar sizda million qator bo'lsa, siz shunchaki tanlay olmaysiz. OFFSET/LIMIT talab qilinadi. Bu variant uchun kim? Va kim autoCommit bilan o'ynash tarafdori?

Bu erda, odatdagidek, eng kutilmagan variant to'g'ri bo'lib chiqadi. Va agar siz to'satdan autoCommit-ni o'chirib qo'ysangiz, bu yordam beradi. Nega bunday? Ilm bu haqda bilmaydi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Biroq, sukut bo'yicha, Postgres ma'lumotlar bazasiga ulangan barcha mijozlar butun ma'lumotlarni oladi. PgJDBC bu borada istisno emas, u barcha qatorlarni tanlaydi.

FetchSize mavzusida o'zgarish mavjud, ya'ni siz alohida bayonot darajasida aytishingiz mumkin, bu erda ma'lumotlarni 10, 50 ga tanlang. Lekin bu autoCommitni o'chirmaguningizcha ishlamaydi. AutoCommit o'chirilgan - u ishlay boshlaydi.

Ammo kodni ko'rib chiqish va setFetchSize-ni hamma joyda sozlash noqulay. Shuning uchun biz butun ulanish uchun standart qiymatni aytadigan sozlamani yaratdik.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Biz shunday dedik. Parametr sozlandi. Va biz nima oldik? Agar biz kichik miqdorlarni tanlasak, masalan, bir vaqtning o'zida 10 qatorni tanlasak, unda bizda juda katta qo'shimcha xarajatlar bor. Shuning uchun, bu qiymat taxminan yuzga o'rnatilishi kerak.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Ideal holda, albatta, siz uni baytlarda qanday cheklashni hali ham o'rganishingiz kerak, ammo retsept quyidagicha: defaultRowFetchSize-ni yuzdan ortiq qilib belgilang va xursand bo'ling.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Keling, ma'lumotlarni kiritishga o'tamiz. Qo'shish osonroq, turli xil variantlar mavjud. Masalan, INSERT, VALUES. Bu yaxshi variant. Siz “INSERT SELECT” deyishingiz mumkin. Amalda ham xuddi shunday. Ishlashda farq yo'q.

Kitoblarda aytilishicha, siz Batch bayonotini bajarishingiz kerak, kitoblarda aytilishicha, siz bir nechta qavslar bilan murakkabroq buyruqlarni bajarishingiz mumkin. Postgres esa ajoyib xususiyatga ega - siz NOSSIYA qilishingiz mumkin, ya'ni buni tezroq bajarishingiz mumkin.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Agar siz uni o'lchasangiz, yana qiziqarli kashfiyotlar qilishingiz mumkin. Bu qanday ishlashini xohlaymiz? Biz keraksiz buyruqlarni tahlil qilmaslik va bajarmaslikni xohlaymiz.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Amalda, TCP buni amalga oshirishga imkon bermaydi. Agar mijoz so'rov yuborish bilan band bo'lsa, ma'lumotlar bazasi bizga javob yuborishga urinishda so'rovlarni o'qimaydi. Yakuniy natija shundaki, mijoz ma'lumotlar bazasi so'rovni o'qishini kutadi va ma'lumotlar bazasi mijozning javobni o'qishini kutadi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Va shuning uchun mijoz vaqti-vaqti bilan sinxronizatsiya paketini yuborishga majbur bo'ladi. Qo'shimcha tarmoq shovqinlari, ortiqcha vaqtni yo'qotish.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir SitnikovVa biz ularni qanchalik ko'p qo'shsak, shunchalik yomonlashadi. Haydovchi juda pessimistik va ularni tez-tez qo'shib qo'yadi, chiziqlar hajmiga qarab har 200 qatorda bir marta va hokazo.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

https://github.com/pgjdbc/pgjdbc/pull/380

Siz faqat bitta chiziqni tuzatasiz va hamma narsa 10 marta tezlashadi. Bo'lib turadi. Nega? Odatdagidek, shunga o'xshash doimiy bir joyda allaqachon ishlatilgan. Va "128" qiymati to'plamdan foydalanmaslikni anglatadi.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Java mikrobenchmark jabduqlar

Bu rasmiy versiyaga kiritilmagani yaxshi. Chiqarish boshlanishidan oldin topilgan. Men beradigan barcha ma'nolar zamonaviy versiyalarga asoslangan.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Keling, sinab ko'raylik. Biz InsertBatch-ni oddiy o'lchaymiz. Biz InsertBatch-ni bir necha marta o'lchaymiz, ya'ni bir xil narsa, lekin juda ko'p qiymatlar mavjud. Qiyin harakat. Buni hamma ham qila olmaydi, lekin bu juda oddiy harakat, COPY dan ancha oson.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

KOPYA qilishingiz mumkin.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Va buni tuzilmalarda qilishingiz mumkin. Foydalanuvchining standart turini e'lon qiling, massivni o'tkazing va to'g'ridan-to'g'ri jadvalga INSERT ni kiriting.

Agar siz pgjdbc/ubenchmsrk/InsertBatch.java havolasini ochsangiz, bu kod GitHub-da. U erda qanday so'rovlar yaratilganligini aniq ko'rishingiz mumkin. Bu muhim emas.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Biz ishga tushirdik. Va biz tushungan birinchi narsa, to'plamdan foydalanmaslik shunchaki mumkin emasligi edi. Barcha to'plam variantlari nolga teng, ya'ni bir martalik bajarish bilan solishtirganda bajarish vaqti amalda nolga teng.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Biz ma'lumotlarni kiritamiz. Bu juda oddiy jadval. Uch ustun. Va biz bu erda nimani ko'ramiz? Biz ushbu uchta variantning barchasini taxminan taqqoslash mumkinligini ko'ramiz. Va COPY, albatta, yaxshiroq.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Bu biz qismlarni joylashtirganda. Bitta VALUES qiymati, ikkita VALUES qiymati, uchta VALUES qiymati deb aytganimizda yoki ulardan 10 tasini vergul bilan ajratib ko'rsatdik. Bu hozir faqat gorizontal. 1, 2, 4, 128. Ko'rinib turibdiki, ko'k rangda chizilgan Batch Insert uni ancha yaxshi his qiladi. Ya'ni, bir vaqtning o'zida bittadan kiritganingizda yoki hatto to'rttasini kiritganingizda, u ikki baravar yaxshi bo'ladi, chunki biz VALUES ichiga biroz ko'proq joylashtirdik. Kamroq EXECUTE operatsiyalari.

Kichik hajmlarda COPY dan foydalanish juda umidsiz. Birinchi ikkitasida ham chizmadim. Ular jannatga, ya'ni COPY uchun bu yashil raqamlarga boradilar.

Agar sizda kamida yuzta qator ma'lumotlar mavjud bo'lsa, COPY dan foydalanish kerak. Ushbu ulanishni ochish uchun qo'shimcha xarajatlar katta. Rostini aytsam, men bu yo'nalishda qazmadim. Men To'plamni optimallashtirdim, lekin COPY emas.

Keyin nima qilamiz? Biz sinab ko'rdik. Biz tuzilmalardan yoki bir nechta ma'nolarni birlashtirgan aqlli baktdan foydalanishimiz kerakligini tushunamiz.

PostgreSQL va JDBC barcha sharbatni siqib chiqaradi. Vladimir Sitnikov

Bugungi hisobotdan nimani olib tashlashingiz kerak?

  • PreparedStatement - bu bizning hamma narsamiz. Bu hosildorlik uchun juda ko'p narsa beradi. Bu malhamda katta flop hosil qiladi.
  • Va siz 6 marta TUSHUN TAHLIL QILISHingiz kerak.
  • Muammoli so'rovlarimizning qolgan foizini tuzatish uchun biz OFFSET 0 ni va +0 kabi hiylalarni suyultirishimiz kerak.

Manba: www.habr.com

a Izoh qo'shish