PostgreSQL ma'lumotlarni qanday saqlaydi?
Ko'pchilikning hayolgia keladigan birinchi javob – jadval(table)larda. Lekin shu table o'zi aslida nima va qanday ishlaydi?
Birinchi bilishimiz kerak bo'lgan narsa – PostgreSQLda biz kiritadigan ma'lumotlar tablening o'zida saqlanmaydi. Table bu ma'lumotlarning o'zini saqlaydigan emas, balki o'sha ma'lumot qayerda saqlanganini ko'rsatib turadigan heap nomli ma'lumotlar tuzilmasi (data structure)dan iborat. Bu qaysidir ma'noda frontendga o'xshash: o'zida ma'lumot yo'q, lekin uni qayerdan olishni biladi.
Xo'sh, unda haqiqiy ma'lumotlar qanday saqlanadi?
PostgreSQL haqiqiy ma'lumotlarni heap tuple (yoki shunchaki tuple) nomli alohida tuzilmalarda saqlaydi.
Heap tuple bu (odatda) tabledagi bitta record(row) saqlangan obyekt. Ya'ni bitta rowdagi qiymatlar bitta tuple sifatida, ketma-ket joylashadi. Va har bitta tuplening o'zining IDsi bor. Biz biladigan jadvalda biz qo'shgan ustunlardan tashqari yana bitta ustun – TID(Tuple ID) ham bor va aynan o'sha qiymat shu rowga tegishli ma'lumotlar qaysi tupleda turganini ko'rsatadi.
*qo'shimchaDemak, ma'lumotlar tupleda saqlanishini bilib oldik. Bir qancha tuplelar birlashib, page yoki blokni tashkil qiladi. Bitta pagening o'lchami odatda, 8 KB bo'ladi va har bitta page fayl sistemasida bitta fayl sifatida saqlanadi. Albatta, bu faylda tuplelardan tashqari bir qancha metadata ham saqlanadi.
Shunday qilib, bitta tabledagi ma'lumotlar bir qancha (kamida bitta) pagelarda saqlanadi.
Yana bir gap, doimiy xotirada RAMga o'xshab istalgan joydagi istalgan baytni to'g'ridan-to'g'ri ololmaymiz. Birinchidan, doimiy xotira RAMga o'xshab, addresslanmagan. Ikkinchidan, har bir baytni asosiy xotiradan alohida-alohida o'qib olish ancha "qimmat"ga tushadi. Shuning uchun doimiy xotiraga bir marta borganda ko'proq ma'lumot olib qaytish kerak. PostgreSQL asosiy xotiradan ma'lumotlarni page bo'yicha ko'chiradi, ya'ni bitta faylni to'liqligicha yuklab oladi.
Bu degani, agar bizga bitta pagedagi faqat 1 ta qiymat kerak bo'lsa ham, butun pageni ko'chirib olishga majburmiz.
Ma'lumotlar to'liq tuplelardan saqlanadimi? Yo'q.
Katta hajmli ma'lumotlarni doimiy xotiradan ko'chirib olish ancha resurs oladi. Shuning uchun ularni faqatgina eng kerakli vaziyatlardagina ko'chirib olish kerak.
Masalan,
SELECT * FROM test_table WHERE id = 3;
mana shu query ishga tushganida agar indeks bo'lmasa id bo'yicha izlash uchun hamma id larni olishimiz kerak. Lekin tepada kelishganimizdek, bizga faqatgina id kerak bo'lsa ham butun boshli tuple va o'sha tuple joylashgan blokni ko'chirib olishimiz kerak.
Agar keyingi ustunda 1 GB hajmli fayl to'g'ridan-to'g'ri saqlansa, shunchaki bitta IDni (aslida faqatgina izlash uchun) olish uchun butun boshli faylni ham yuklab olishga to'g'ri keladi.
Xo'sh, katta hajmli ma'lumotlarni tupleda saqlay olmasak, unda qanday saqlaymiz? Oddiy yechim. Shunchaki ma'lumotni boshqa joyda saqlaymiz va tupleda faqatgina shu ma'lumot turgan joy manzilini saqlaymiz. Tupleni RAMga ko'chirib olayotganda esa 1 GBli ma'lumotni emas, faqatgina uning addressini olamiz. Qarabsizki, six ham kabob ham kuymaydi.
Umuman olganda, PostgreSQL hatto varchar va textni ham tupleda saqlamaydi. Xuddi tepada aytilganidek ularni ham alohida saqlab, tupleda ularga pointer saqlaydi.
Albatta, bu ma'lumotlar juda yuzaki va aslidan biroz o'zgartirilgan(osonroq tushunish uchun). Lekin o'ylaymanki, bu qisqa maqola kim uchundir shu mavzuda izlanib ko'rishga turtki bo'la oladiganlar darajada foydali bo'ladi.