بخش اول: ورود به جهان قدرتمند PostgreSQL
بخش دوم : مکانیزم های حرفه‌ای مدیریت ذخیره سازی و تضمین مقیاس پذیری پستگرس
بخش سوم : تحلیل و بهینه‌سازی اجرای کوئری در PostgreSQL
بخش چهارم: استراتژی‌های پشتیبان‌گیری و بازیابی اطلاعات
بخش پنجم: راهکارهای دسترس‌پذیری بالا و مقیاس‌پذیری
بخش ششم: پایش، مانیتورینگ و عیب‌یابی در PostgreSQL
کارگاه‌ها و مثال‌های کاربردی

فایلهای FSM و VM در کنار فایل اصلی داده هر جدول، دقیقا چه نقشی را بر عهده دارند؟ 🎥

در دنیای پایگاه داده‌های مدرن، عملکرد و کارایی اغلب به جزئیات پنهان زیر سطح داده‌ها بستگی دارد. در PostgreSQL، جدول‌ها تنها فایل‌های داده اصلی نیستند که ردیف‌ها را ذخیره می‌کنند؛ بلکه چند فایل جانبی کوچک وجود دارند که نقش حیاتی در سرعت و بهینه‌سازی عملیات دارند. دو نمونه کلیدی از این فایل‌ها Free Space Map (_fsm) و Visibility Map (_vm) هستند.

تصور کنید جدول شما یک ساختمان است: صفحات داده، واحدهای آپارتمان هستند و ردیف‌ها ساکنان. FSM نقش یک «مشاور املاک دقیق» را بازی می‌کند، همیشه می‌داند کدام صفحات فضای خالی دارند و به PostgreSQL کمک می‌کند تا هنگام درج ردیف‌های جدید، بدون هدر دادن فضا، سریعاً محل مناسب را پیدا کند. از سوی دیگر، VM مانند یک «لیست VIP» عمل می‌کند و به سیستم می‌گوید کدام صفحات کاملاً قابل مشاهده و پایدار هستند؛ این اطلاعات به Index-Only Scan و VACUUM اجازه می‌دهد تا با صرف حداقل I/O، عملیات خود را انجام دهند.

در این کارگاه، ما به بررسی این دو فایل جانبی می‌پردازیم، نحوه عملکرد آن‌ها را می‌آموزیم و با ابزارهای داخلی PostgreSQL روش‌های پایش و تحلیل آن‌ها را تمرین خواهیم کرد. شما با درک عمیق این فایل‌ها، نه تنها قادر خواهید بود عملکرد جداول خود را بهینه کنید، بلکه می‌توانید مشکلات بالقوه مربوط به رشد غیرکارآمد فایل‌ها و تراکنش‌های طولانی را سریع‌تر شناسایی کنید.


بخش اول: Free Space Map (_fsm) – «فهرست فضای آزاد جدول»

۱.۱ FSM چیست؟

هر جدول (و ایندکس) در PostgreSQL یک فایل اصلی داده دارد که ردیف‌ها را ذخیره می‌کند. در کنار آن، یک Free Space Map با نام <relfilenode>_fsm وجود دارد که میزان فضای آزاد موجود در هر صفحه ۸ کیلوبایتی جدول را ثبت می‌کند.

چرا به FSM نیاز داریم؟
هنگامی که یک ردیف جدید وارد جدول می‌شود، PostgreSQL باید صفحه‌ای پیدا کند که فضای کافی برای ذخیره آن داشته باشد. بدون FSM، پایگاه داده باید یا:

  • تمام صفحات را به‌صورت ترتیبی جستجو کند (هزینه بالا)، یا
  • همیشه ردیف‌ها را در انتهای فایل اضافه کند (باعث رشد سریع فایل و استفاده ناکارآمد از فضای موجود می‌شود).

FSM مانند یک فهرست سریع عمل می‌کند و صفحات مناسب برای درج ردیف جدید را مشخص می‌کند، بدون آنکه فضای موجود هدر برود.


۱.۲ عملکرد FSM (خلاصه)

FSM به صورت یک درخت از صفحات ۸ کیلوبایتی ذخیره می‌شود:

  • گره‌های برگ: هر برگ مربوط به یک صفحه داده است و یک بایت (۰–۲۵۵) را برای نشان دادن میزان فضای آزاد روی آن صفحه ذخیره می‌کند.
  • گره‌های داخلی: حداکثر فضای آزاد فرزندان خود را جمع‌بندی می‌کنند تا جستجو بتواند کل زیرشاخه‌ها را نادیده بگیرد.
  • نرمال‌سازی: از مقیاس لگاریتمی استفاده می‌شود، مثلاً صفحات با ۰–۳۱ بایت فضای آزاد → دسته ۰، ۳۲–۶۳ بایت → دسته ۱، …، > ۸۱۶۰ بایت → دسته ۲۵۵.

این روش، اطلاعات فضای آزاد را فشرده می‌کند و همچنان برای انتخاب صفحه مناسب کافی است.


۱.۳ تمرین ۱: مشاهده FSM با pg_freespacemap

ابتدا یک جدول تست ایجاد و مقداری داده وارد می‌کنیم:

CREATE TABLE fsm_test (
    id serial,
    data text
);

INSERT INTO fsm_test (data)
SELECT 'some text'
FROM generate_series(1, 1000);

اکنون افزونه pg_freespacemap را فعال می‌کنیم:

CREATE EXTENSION IF NOT EXISTS pg_freespacemap;

و فضای آزاد جدول را بررسی می‌کنیم:

SELECT * FROM pg_freespace('fsm_test');

خروجی مشابه زیر خواهد بود:

 blkno | avail 
-------+-------
     ۰ | ۰
     ۱ | ۰
     ۲ | ۰
   ... | ...
     ۵ | ۲۵۹۸
  • avail میزان فضای آزاد (بر حسب بایت) برای هر صفحه است.
  • در جدول تازه ایجاد شده، صفحات ابتدایی فضای خالی زیادی ندارند و تنها آخرین صفحه ممکن است حاوی فضای خالی باشد.

حالا چند ردیف حذف می‌کنیم تا ببینیم FSM فوراً به‌روز نمی‌شود:

DELETE FROM fsm_test WHERE id % 3 = 0;
SELECT * FROM pg_freespace('fsm_test');

مقدار فضای آزاد هنوز تغییر نکرده است. علت: FSM عمدتاً توسط VACUUM به‌روزرسانی می‌شود.

اجرای یک VACUUM دستی:

VACUUM fsm_test;
SELECT * FROM pg_freespace('fsm_test');

اکنون مقدار avail برای صفحاتی که ردیف حذف شده‌اند، افزایش یافته است و FSM از فضای آزاد آگاه شده است.


۱.۴ تمرین ۲: مشاهده محتویات یک صفحه FSM با pageinspect

افزونه pageinspect امکان مشاهده صفحات خام FSM را می‌دهد:

CREATE EXTENSION IF NOT EXISTS pageinspect;

ابتدا اندازه فایل FSM (تعداد صفحات) را بررسی کنید:

SELECT relname, relfilenode
FROM pg_class
WHERE relname = 'fsm_test';

حالا اولین صفحه FSM را بررسی کنید:

SELECT * FROM fsm_page_contents(get_raw_page('fsm_test', 'fsm', 0));

خروجی یک نمایش متنی از گره‌های ذخیره شده در آن صفحه است:

۰: leaf: avg 150, max 255, nodes ...

برای درک عمیق‌تر، می‌توانید توضیحات منبع در src/backend/storage/freespace/README را مطالعه کنید.


۱.۵ نکته مهم: FSM همیشه دقیق نیست
  • FSM یک راهنمای تقریبی است، نه تضمین واقعی. مقادیر ممکن است کمی بزرگ‌تر از واقعیت باشند چون به‌روزرسانی‌ها دسته‌ای انجام می‌شوند.
  • تراکنش‌های طولانی می‌توانند VACUUM را متوقف کنند و باعث قدیمی شدن FSM شوند.
  • درج‌های حجمی صفحات جدید را ایجاد می‌کنند اما FSM صفحات موجود را به‌روز نمی‌کند – که مشکلی ایجاد نمی‌کند چون صفحات جدید هنگام ایجاد به FSM اضافه می‌شوند.

نگرش کلیدی: FSM یک بهینه‌سازی عملکرد است. اگر فکر می‌کنید فضای جدول به‌درستی استفاده نمی‌شود، FSM را بررسی و VACUUM را اجرا کنید.


بخش دوم: Visibility Map (_vm) – «چک‌لیست دیدپذیری جدول»

۲.۱ VM چیست؟

Visibility Map یک فایل کمکی دیگر (<relfilenode>_vm) است که برای هر صفحه دو بیت ذخیره می‌کند:

  1. all-visible: همه ردیف‌های صفحه برای تمام تراکنش‌های جاری و آینده قابل دیدن هستند
  2. all-frozen: همه ردیف‌ها منجمد شده‌اند (مهم برای VACUUM ضد wraparound)

چرا VM مهم است؟

  • Index-Only Scan: اگر صفحه‌ای همه ردیف‌ها را قابل دیدن دارد، ایندکس می‌تواند داده را مستقیم ارائه کند و نیازی به مراجعه به صفحه heap نیست.
  • Skip در VACUUM: VACUUM می‌تواند صفحات all-visible را نادیده بگیرد، کاهش I/O و افزایش سرعت را امکان‌پذیر می‌کند.

۲.۲ ساختار VM

VM یک bitmap ساده است که در صفحات ۸ کیلوبایتی ذخیره می‌شود. برای جدولی با N صفحه، حجم VM تقریباً N / (8 * 8192) صفحه است – بسیار کوچک نسبت به حجم جدول.


۲.۳ تمرین ۳: مشاهده VM با pg_visibility

افزونه را فعال کنید:

CREATE EXTENSION IF NOT EXISTS pg_visibility;

و VM جدول تست را بررسی کنید:

SELECT * FROM pg_visibility_map('fsm_test');

خروجی شامل شماره صفحه و دو پرچم boolean (all_visible, all_frozen) است.

اجرای VACUUM باعث تنظیم پرچم‌ها می‌شود:

VACUUM fsm_test;
SELECT * FROM pg_visibility_map('fsm_test');

اکثر صفحات اکنون all_visible خواهند بود.


۲.۴ تمرین ۴: تغییر VM هنگام به‌روزرسانی

یک ردیف روی صفحه‌ای که all-visible است را به‌روزرسانی کنید:

UPDATE fsm_test SET data = 'modified' WHERE id = 1;
SELECT * FROM pg_visibility_map('fsm_test') WHERE blkno = 0;
  • بیت all_visible بلافاصله پاک می‌شود (hint است، WAL ثبت نمی‌شود)
  • اجرای VACUUM دوباره بیت را به true بازمی‌گرداند

۲.۵ تأثیر بر عملکرد
  • Index-Only Scan: با EXPLAIN (ANALYZE, BUFFERS) بررسی کنید؛ اگر Heap Fetches: 0 مشاهده کردید، VM به بهینه شدن پرس‌وجو کمک کرده است.
  • Skip در VACUUM: هر چه تعداد صفحات all-visible بیشتر باشد، VACUUM سریع‌تر اجرا می‌شود.

بخش سوم: نگرش و بهترین شیوه‌ها برای FSM و VM

۳.۱ مدل ذهنی

  • FSM = «مشاور املاک جدول» – صفحات دارای فضای آزاد را می‌شناسد
  • VM = «لیست VIP جدول» – صفحات ایمن برای نادیده گرفتن در VACUUM و Index Scan

این فایل‌ها همیشه کمی عقب‌تر از جدول هستند و این طبیعی است؛ چون برای بهینه‌سازی، نه صحت داده، استفاده می‌شوند.


۳.۲ پایش
  • بررسی سلامت FSM:
SELECT count(*) FROM pg_freespace('fsm_test') WHERE avail = 0;
  • بررسی پوشش VM:
SELECT count(*) FROM pg_visibility_map('fsm_test') WHERE all_visible;
  • استفاده از pg_stat_user_tables: ستون‌هایی مانند n_dead_tup, last_vacuum, vacuum_count به درک وضعیت کمک می‌کنند

۳.۳ مشکلات رایج
  • تراکنش‌های طولانی مانع پاکسازی ردیف‌های مرده و به‌روزرسانی FSM/VM می‌شوند
  • Autovacuum ناکافی – پارامترهای autovacuum_vacuum_scale_factor و autovacuum_vacuum_threshold باید تنظیم شوند
  • نادیده گرفتن bloat – اگر FSM صفحات خالی نشان می‌دهد اما جدول همچنان بزرگ است، احتمال bloat وجود دارد
  • عدم استفاده از افزونه‌ها – pg_freespacemap و pg_visibility تنها خواندن داده دارند و در تشخیص مشکلات بسیار مفید هستند

۳.۴ اقدامات نگهداری
  • اجرای منظم autovacuum
  • پس از حذف یا به‌روزرسانی حجیم، VACUUM یا VACUUM ANALYZE دستی
  • برای بارگذاری حجیم، اجرای VACUUM برای بازسازی اطلاعات FSM
  • در صورت فساد نادر FSM/VM، می‌توان با VACUUM FULL یا CLUSTER بازسازی کرد (با احتیاط)

۳.۵ سناریوهای عملی
  1. کندی INSERT‌ها → FSM قدیمی است، VACUUM اجرا کنید
  2. Index-only scan هنوز Heap Fetch می‌کند → بیت VM تنظیم نشده، VACUUM و بررسی pg_visibility
  3. جدول بزرگ اما فضای آزاد کم → طبیعی، یا VACUUM اجرا نشده، یا bloat وجود دارد

📹 محتوای ویدئویی کارگاه در بخش زیر قابل مشاهده است.

فروشگاه
جستجو
دوره ها

لطفا کلمات کلیدی را وارد کنید