فصل ۱: شروع — نصب، معماری و ابزارها

چرا PostgreSQL؟ جایگاه، نسخه‌ها و تفاوت با MySQL

دیتابیسی که «درستی داده» را جدی می‌گیرد

PostgreSQL (به اختصار «پستگرس») ریشه در پروژه‌ی POSTGRES دانشگاه برکلی در دهه‌ی ۱۹۸۰ دارد و از ۱۹۹۶ با نام فعلی به‌صورت متن‌باز توسعه داده می‌شود. پشت آن یک شرکت واحد نیست؛ یک جامعه‌ی جهانی و ده‌ها شرکت با هم آن را جلو می‌برند و مجوزش (PostgreSQL License، شبیه BSD) هر استفاده‌ی تجاری را بدون هزینه و بدون الزام انتشار کد مجاز می‌کند. برای ما یک مزیت عملی دیگر هم دارد: هیچ بخشی از آن پشت لایسنس اشتراکی یا فعال‌سازی آنلاین نیست که با تحریم از کار بیفتد.

چه چیزی آن را متمایز می‌کند

  • قیدها واقعاً اجرا می‌شوند: رشته‌ی بلندتر از ستون بی‌صدا بریده نمی‌شود، تاریخ نامعتبر به صفر تبدیل نمی‌شود و تبدیل نوع ضمنیِ خطرناک انجام نمی‌شود؛ خطا می‌گیرید.
  • DDL تراکنشی: CREATE TABLE و ALTER TABLE را می‌توان داخل یک تراکنش گذاشت؛ اگر مرحله‌ی سوم یک migration شکست بخورد، دو مرحله‌ی قبلی هم برمی‌گردند. در MySQL هر DDL یک commit ضمنی است.
  • توسعه‌پذیری: نوع داده، تابع، عملگر و حتی نوع ایندکس جدید را می‌شود به‌صورت اکستنشن اضافه کرد؛ PostGIS، pgvector و TimescaleDB همه اکستنشن‌اند.
  • SQL غنی: Window Function، CTE بازگشتی، LATERAL، jsonb با ایندکس GIN، انواع range، قید EXCLUDE و Full-Text Search داخلی.
  • MVCC: خواننده‌ها نویسنده‌ها را معطل نمی‌کنند و برعکس؛ بهای آن نیاز به VACUUM است که در فصل ۶ کامل می‌بینیم.

مقایسه‌ی کوتاه با MySQL

موضوعPostgreSQLMySQL (InnoDB)
DDL داخل تراکنشبله، قابل ROLLBACKخیر، commit ضمنی
مدل اتصالیک پروسه برای هر اتصال؛ pooler تقریباً ضرورییک thread برای هر اتصال
ایندکس جزئی (partial)داردندارد
JSONjsonb باینری با ایندکس GIN روی کل سندJSON با ایندکس روی ستون‌های مجازی
انواع ویژهarray، range، uuid، inet، enum واقعیمحدودتر
نگهداریVACUUM و autovacuumpurge داخلی InnoDB

نسخه‌ها و چرخه‌ی انتشار

هر سال حدود مهرماه یک نسخه‌ی اصلی منتشر می‌شود: 16 در ۲۰۲۳، 17 در ۲۰۲۴ و 18 در ۲۰۲۵. هر نسخه‌ی اصلی پنج سال به‌روزرسانی می‌گیرد و هر سه ماه یک نسخه‌ی فرعی (مثل 17.6) می‌آید. از نسخه‌ی 10 به بعد، عدد اول نسخه‌ی اصلی است: رفتن از 17.2 به 17.6 فقط عوض کردن باینری‌ها و یک restart است، اما رفتن از 16 به 17 ارتقای واقعی با pg_upgrade یا dump/restore لازم دارد (فصل ۷).

SELECT version();
SHOW server_version_num;      -- 170006 یعنی 17.6
SELECT current_setting('server_version_num')::int >= 160000 AS is_16_or_newer;

نکته‌هایی که کمتر کسی می‌داند

  • نام‌های بدون کوتیشن به حروف کوچک تبدیل می‌شوند: CREATE TABLE Orders همان orders است. اما اگر ابزاری جدول را با "Orders" بسازد، از آن به بعد همیشه باید با دابل‌کوتیشن صدایش کنید. از روز اول همه‌چیز را کوچک و snake_case بنویسید.
  • رشته با تک‌کوتیشن است و شناسه با دابل‌کوتیشن؛ WHERE name = "ali" یعنی «ستونی به نام ali» و خطای column does not exist می‌دهد. این اولین دام کسانی است که از MySQL می‌آیند.
  • در release notes نسخه‌های فرعی گاهی نوشته می‌شود «پس از ارتقا این نوع ایندکس‌ها را REINDEX کنید»؛ بخش Migration هر نسخه‌ی فرعی را همیشه بخوانید.
  • در اسکریپت‌ها به‌جای تجزیه‌ی رشته‌ی version() از server_version_num استفاده کنید؛ یک عدد قابل‌مقایسه است.
  • حتی داخل یک تراکنش می‌توانید CREATE INDEX و DROP TABLE را امتحان و بعد ROLLBACK کنید؛ روشی امن برای آزمودن اثر یک تغییر روی پلن کوئری (به‌جز CREATE INDEX CONCURRENTLY که داخل تراکنش مجاز نیست).

برای ذخیره‌ی پیشرفت و شرکت در آزمون، وارد شوید — رایگان است.