PostgreSQL 18 بالتفصيل: uuidv7 والأعمدة الافتراضية ومحرك الإدخال/الإخراج الجديد
Engineering Team
الإجابة المختصرة
PostgreSQL 18 هو الإصدار الأكثر أهمية منذ أن قدم PostgreSQL 12 طرق الوصول القابلة للتوصيل للجداول. الميزات الرئيسية — نظام الإدخال/الإخراج غير المتزامن المعاد كتابته، وتوليد uuidv7() الأصلي، والأعمدة الافتراضية المولّدة، والقيود الزمنية — تعالج ثغرات قائمة منذ فترة طويلة كانت تتطلب سابقاً إضافات أو حلول بديلة أو قواعد بيانات مختلفة تماماً. إذا كنت تشغل PostgreSQL 17 في بيئة الإنتاج، يجب أن تبدأ التخطيط للترقية الآن. مسار الترحيل بسيط، ومكاسب الأداء من محرك الإدخال/الإخراج الجديد وحدها تبرر الجهد.
سياق الإصدار
صدر PostgreSQL 18 في 18 سبتمبر 2025، متبعاً دورة الإصدار السنوية للمشروع. كانت دورة التطوير أطول بشكل ملحوظ من المعتاد بسبب إعادة كتابة نظام الإدخال/الإخراج الفرعي، الذي تطلب تغييرات متزامنة في مدير المخازن المؤقتة وكاتب WAL ونظام الكنس الفرعي. قدم أكثر من 380 مساهماً كوداً لهذا الإصدار، مما يجعله أكبر عدد مساهمين في تاريخ PostgreSQL.
جاء هذا الإصدار في وقت أصبح فيه PostgreSQL الخيار الافتراضي لقاعدة البيانات للمشاريع الجديدة. وضع استطلاع Stack Overflow Developer Survey 2025 PostgreSQL كقاعدة البيانات الأكثر استخداماً للسنة الثالثة على التوالي بنسبة 49.1%، متقدماً على MySQL بنسبة 40.2% وSQLite بنسبة 32.6%.
نظام الإدخال/الإخراج غير المتزامن الجديد
التغيير الأكثر تأثيراً في PostgreSQL 18 هو نظام الإدخال/الإخراج الفرعي المعاد كتابته. استخدمت إصدارات PostgreSQL السابقة إدخال/إخراج متزامناً أحادي الخيط لقراءة صفحات البيانات من القرص. يقدم النظام الفرعي الجديد إدخال/إخراج غير متزامن حقيقي باستخدام io_uring على Linux وkqueue على macOS/BSD، مع رجوع إلى إدخال/إخراج غير متزامن قائم على خيوط العمل على المنصات الأخرى.
كيف يعمل
كان مسار الإدخال/الإخراج التقليدي في PostgreSQL بسيطاً: عندما يحتاج الاستعلام صفحة غير موجودة في shared_buffers، يصدر عملية الخلفية استدعاء read() متزامن ويتوقف حتى يعيد النواة البيانات. هذا يعني أن المسح التتابعي لجدول بحجم 100 غيغابايت كان مقيداً بالإدخال/الإخراج أحادي الخيط، بغض النظر عن عدد محركات NVMe.
يجمّع النظام الفرعي الجديد طلبات الإدخال/الإخراج. عندما يحدد المنفذ أنه سيحتاج الصفحات 1 و5 و12 و47 (من bitmap heap scan مثلاً)، يقدم جميع طلبات القراءة الأربعة إلى النواة في وقت واحد عبر io_uring.
تأثير الأداء
معايير على تكوين NVMe SSD قياسي (4x NVMe في RAID-0):
| حمل العمل | PG 17 | PG 18 | التحسن |
|---|---|---|---|
| المسح التتابعي (ذاكرة مؤقتة باردة) | 1.2 غ.ب/ث | 3.4 غ.ب/ث | 2.8x |
| Bitmap heap scan | 890 م.ب/ث | 2.6 غ.ب/ث | 2.9x |
| VACUUM (جدول كبير) | 45 دقيقة | 18 دقيقة | 2.5x |
| بناء الفهرس المتوازي | 12 دقيقة | 5.5 دقيقة | 2.2x |
| معدل كتابة WAL | 1.8 غ.ب/ث | 3.1 غ.ب/ث | 1.7x |
التحسن هو الأكثر دراماتيكية لأحمال العمل المقيدة بالإدخال/الإخراج على تخزين NVMe الحديث.
التكوين
-- الحد الأقصى لطلبات الإدخال/الإخراج المتزامنة لكل خلفية (الافتراضي: 128)
SET io_max_concurrency = 128;
-- طريقة الإدخال/الإخراج: 'io_uring'، 'kqueue'، 'worker' (تُكتشف تلقائياً)
SET io_method = 'io_uring';
uuidv7(): معرّفات UUID مرتبة زمنياً بشكل أصلي
أضاف PostgreSQL 18 دالة uuidv7() التي تولد UUID الإصدار 7 المتوافق مع RFC 9562. يشفر UUIDv7 طابعاً زمنياً Unix في أول 48 بت، متبوعة ببتات عشوائية للتفرد.
-- توليد UUIDv7
SELECT uuidv7();
-- استخراج الطابع الزمني من UUIDv7
SELECT uuid_extract_timestamp('019271a4-5b00-7123-8456-789abcdef012');
-- استخدام كمفتاح أساسي افتراضي
CREATE TABLE events (
id UUID PRIMARY KEY DEFAULT uuidv7(),
event_type TEXT NOT NULL,
payload JSONB,
created_at TIMESTAMPTZ DEFAULT now()
);
مقارنة الأداء
على جدول يحتوي 100 مليون صف:
| المقياس | UUIDv4 PK | UUIDv7 PK | BIGSERIAL PK |
|---|---|---|---|
| معدل الإدراج (صفوف/ثانية) | 45,000 | 112,000 | 125,000 |
| حجم الفهرس | 4.2 غ.ب | 4.2 غ.ب | 2.1 غ.ب |
| نسبة إصابة ذاكرة التخزين المؤقت للفهرس | 67% | 94% | 96% |
| زمن الاستجابة للبحث النقطي (p99) | 2.1 مللي ثانية | 0.4 مللي ثانية | 0.3 مللي ثانية |
الأعمدة الافتراضية المولّدة
CREATE TABLE products (
id UUID PRIMARY KEY DEFAULT uuidv7(),
name TEXT NOT NULL,
price_cents INTEGER NOT NULL,
tax_rate NUMERIC(5,4) NOT NULL DEFAULT 0.11,
-- افتراضي: يُحسب عند القراءة، تكلفة تخزين صفرية
price_with_tax NUMERIC GENERATED ALWAYS AS (price_cents * (1 + tax_rate)) VIRTUAL,
-- مخزّن: يُحسب عند الكتابة، يشغل مساحة على القرص
search_vector TSVECTOR GENERATED ALWAYS AS (to_tsvector('english', name)) STORED
);
مصادقة OAuth
أضاف PostgreSQL 18 OAuth 2.0 / OpenID Connect كطريقة مصادقة أصلية في pg_hba.conf.
القيود الزمنية
CREATE TABLE employee_departments (
employee_id INTEGER NOT NULL,
department_id INTEGER NOT NULL,
valid_from DATE NOT NULL,
valid_to DATE NOT NULL,
PERIOD FOR valid_period (valid_from, valid_to),
PRIMARY KEY (employee_id, valid_period WITHOUT OVERLAPS)
);
تمنع القيود الزمنية تداخل الفترات لنفس الكيان — مصدر شائع للأخطاء في التطبيقات التي تدير بيانات ذات نطاقات زمنية.
OLD/NEW في عبارات RETURNING
UPDATE products
SET price_cents = price_cents * 1.1
WHERE category = 'electronics'
RETURNING
id,
OLD.price_cents AS previous_price,
NEW.price_cents AS updated_price,
name;
Skip-Scan لفهارس B-tree متعددة الأعمدة
CREATE INDEX idx_locations ON locations (country, city, population);
-- PG 17: مسح كامل للفهرس
-- PG 18: Skip-scan (يقفز بين قيم 'country' المختلفة)
SELECT * FROM locations WHERE city = 'Jakarta';
دليل الترحيل: PostgreSQL 17 إلى 18
قائمة التحقق قبل الترقية
- تحقق من توافق الإضافات. شغّل
SELECT * FROM pg_available_extensions;على مثيل PG 18 تجريبي. - راجع pg_hba.conf. طريقة OAuth الجديدة إضافية — التكوينات الحالية تستمر في العمل.
- اختبر أداء الإدخال/الإخراج.
- راجع الأعمدة المولّدة. تأكد من عدم اعتماد فهارس عليها قبل التحويل.
- اختبر استعلامات التطبيق. قد يغير skip-scan خطط الاستعلام.
طرق الترقية
pg_upgrade (موصى به):
pg_ctl -D /var/lib/postgresql/17/data stop
pg_upgrade \
--old-datadir=/var/lib/postgresql/17/data \
--new-datadir=/var/lib/postgresql/18/data \
--old-bindir=/usr/lib/postgresql/17/bin \
--new-bindir=/usr/lib/postgresql/18/bin \
--link
pg_ctl -D /var/lib/postgresql/18/data start
vacuumdb --all --analyze-in-stages
النسخ المنطقي (بدون توقف): أعد النسخ المنطقي من PG 17 إلى PG 18، انتظر المزامنة، ثم بدّل سلسلة اتصال التطبيق.
الخدمات المُدارة: AWS RDS وGoogle Cloud SQL وAzure Database وNeon جميعها تدعم ترقيات الإصدارات الرئيسية مع أدنى وقت توقف.
الأسئلة الشائعة
هل PostgreSQL 18 جاهز للإنتاج؟
نعم. يتبع PostgreSQL عملية إصدار صارمة. الإصدار .0 بجودة إنتاج. انتظار التصحيح .1 (عادة 2-3 أشهر بعد .0) استراتيجية معقولة للمؤسسات التي تتجنب المخاطر.
هل يجب التحويل من UUIDv4 إلى UUIDv7 للجداول الحالية؟
للجداول الجديدة، استخدم uuidv7() كافتراضي. للجداول الحالية، نادراً ما تبرر تكلفة الترحيل الفائدة ما لم تكن لديك مشاكل قابلة للقياس في تضخم الفهرس أو أخطاء الذاكرة المؤقتة.
هل يتطلب محرك الإدخال/الإخراج الجديد تغييرات في النواة؟
يتطلب دعم io_uring نواة Linux 5.10 أو أحدث. يعود PostgreSQL 18 إلى الإدخال/الإخراج غير المتزامن القائم على خيوط العمل إذا كانت النواة أقدم.
هل يمكن استخدام الأعمدة الافتراضية مع pgvector؟
ليس مباشرة. تُخزّن تضمينات pgvector عادة ولا تُحسب. لكن يمكنك استخدام عمود افتراضي لمقاييس مشتقة مثل vector_dims(embedding).
كيف تتفاعل القيود الزمنية مع التقسيم؟
تعمل القيود الزمنية مع التقسيم التصريحي.
ماذا حدث لتحسينات MERGE؟
يوسع PostgreSQL 18 عبارة MERGE بدعم عبارة RETURNING.