PRODمنصة BaaS الأوروبية السياديةافتح لوحة المعلومات →

الأداء · 11 دقيقة للقراءة

PostgREST: الحدود المعيارية والحقيقية في الإنتاج

Affane Daylami · Fondateur · 18 مايو 2026

العودة إلى بلوق

PostgREST نفسها لا تشكل عنق الزجاجة أبدًا. في مثيلات Aurabase المخصصة، يتم تشغيل نسخة متماثلة باستخدام 50 إلى 250 مللي كور من وحدة المعالجة المركزية و64 إلى 128 ميجابايت من ذاكرة الوصول العشوائي. إنه برنامج Haskell الثنائي خفيف الوزن الذي يترجم طلبات HTTP إلى SQL، لا أكثر. الحدود الحقيقية التي تظهر في الإنتاج موجودة في مكان آخر. تظهر أربعة منها في أغلب الأحيان: ميزانية اتصالات Postgres التي تستهلكها النسخ المتماثلة، وتكلفة COUNT بالضبط ضمن MVCC. يمكن أيضًا أن يظل اقتطاع الاستجابة غير مرئي في الرؤوس، كما هو الحال مع نافذة زمن الوصول بعد كل ترحيل للمخطط.

تم إنشاء هذا النص الإنجليزي تلقائيًا من النص الأصلي الفرنسي ولم تتم مراجعته بعد.
تمت ترجمة هذه الصفحة تلقائيًا. النسخة الإنجليزية موثوقة.

مقالتنا عن توافق مع PostgREST توضح بالتفصيل ما يغطيه الخادم وظيفيًا (المرشحات، والتضمين، وRPC، وRLS) وما يتركه لك. هذا واحد يأتي من مكان آخر. إنه يوثق، باستخدام كود Aurabase ووثائق PostgREST الرسمية كمصادر، أين ولماذا وصل PostgREST فعليًا إلى مستوى ثابت على نطاق واسع. نحن لا نعيد هنا إنتاج بنك الأحمال الذي لم نديره بأنفسنا. تشرح منهجيتنا المعيارية لماذا لا يبدو الرقم المعزول، بدون بروتوكول منشور، موثوقًا بالنسبة لنا.

الأساسيات

  • PostgREST نفسها خفيفة الوزن: 50 إلى 250 مليكور من وحدة المعالجة المركزية، و64 إلى 128 ميجابايت من ذاكرة الوصول العشوائي لكل نسخة متماثلة على مثيلات Aurabase المخصصة. إن إنتاجية HTTP الخام لا تعد أبدًا العامل المقيد في الإنتاج.
  • السقف الحقيقي هو ميزانية اتصال Postgres: PGRST_DB_POOL × النسخ المتماثلة. تم التحقق منها في كود Aurabase: 20 اتصالاً لكل مشروع على المستوى المخصص (10×2)، و4 على المستوى المشترك (2×2). يعد هذا اختيارًا متعمدًا لاستيعاب المزيد من المستأجرين في نفس max_connections.
  • Prefer: count=exact يفرض إجراء مسح MVCC باهظ الثمن على طاولات كبيرة. يوثق PostgREST بديلين أرخص: count=planned و count=estimatedبتكلفة إجمالية تقريبية.
  • يقوم الحد الأقصى db-max-rows (1000 سطر افتراضيًا في Aurabase) باقتطاع الاستجابة دون الإبلاغ عنها في Content-Range (يتم قياسها في الظروف الحقيقية، المفصلة أدناه).
  • بعد ترحيل DDL، تتم إعادة تحميل ذاكرة التخزين المؤقت لمخطط PostgREST بشكل غير متزامن. تعيد بوابة Aurabase المحاولة حتى 8 مرات (حوالي 3.5 ثانية تراكمية في أسوأ الحالات) قبل الاستسلام، وهو سلوك موثق مباشرة في التعليمات البرمجية.
#
المنهجية

ما الذي يقيسه معيار PostgREST وما لا يقيسه

يقيس اختبار إنتاجية HTTP على PostgREST بشكل أساسي Postgres، ونادرًا ما يقيس PostgREST. الخادم عبارة عن طبقة رقيقة من الترجمة أمام القاعدة. في الغالبية العظمى من عمليات التحميل في العالم الحقيقي، يهيمن على وقت الاستجابة استعلام SQL الذي تم تنفيذه، وليس العملية التي أنشأته.

يحتفظ مشروع PostgREST بمستودع مخصص لهذا الموضوع، PostgREST/postgrest-benchmark على GitHub، والذي يتتبع اختلافات الإنتاجية من إصدار إلى إصدار بدلاً من نشر رقم تسويقي معزول. لم نقم بأدائها أو إعادة نشرها هنا. تعتمد نتائجها على الأجهزة والحجم التخطيطي والسيناريو الذي تم اختباره، وهي بالضبط المتغيرات التي يتطلب بروتوكول القياس الخاص بنا توثيقها قبل اقتباس أي رقم.

أسفل PostgREST، يوجد pgbench الذي يقيس الطبقة المهمة حقًا: وقت معاملة SQL تحت التحميل المتزامن. هذه هي أداة قياس أداء PostgreSQL الرسمية (postgresql.org/docs/current/pgbench.html، تم الوصول إليها في 24 أغسطس 2026). بدلاً من إعادة إنتاج هذا البروتوكول هنا، توثق هذه المقالة أربعة قيود معمارية ملموسة لـ PostgREST في الإنتاج، ويتم التحقق من كل منها في كود مصدر Aurabase أو في وثائق المشروع الرسمية.

#
تم التحقق من الكود

البصمة الفعلية لمثيل PostgREST في Aurabase

يتلقى كل مشروع محرك Aurabase Postgres نسختين متماثلتين مخصصتين من PostgREST، في موقع مشترك مع مجموعته. إن بيان Kubernetes الذي ينشرها يحدد موارد متواضعة.

50-250m
وحدة المعالجة المركزية لكل نسخة
طلبات → حدود
64-128
ميغابايت من ذاكرة الوصول العشوائي لكل نسخة
طلبات → حدود
2
النسخ المتماثلة حسب المشروع
التوفر العالي (ص22)

ما تستهلكه هذه النسخ المتماثلة حقًا ليس وحدة المعالجة المركزية: إنها اتصالات بـ Postgres الأساسي. يتصل كل مثيل PostgREST مباشرة بالمثيل الأساسي (-rw)، دون المرور عبر مجمع PgBouncer المنشور للمستأجر. تم تفصيل هذا الاختيار بالفعل في مقالتنا حول توافق PostgREST: تتطلب آلية إعادة تحميل مخطط LISTEN/NOTIFY اتصالاً مستمرًا، غير متوافق مع المُجمِّع في وضع المعاملة. ما تضيفه هذه المقالة: ما هي التكلفة الفعلية، من حيث الاتصالات، وأين تبلغ ذروتها.

يختلف حجم هذا التجمع لكل نسخة متماثلة (PGRST_DB_POOL) عمدًا وفقًا لمستوى المشروع، الذي تم التحقق منه في k8s_tenant.rs، الوظيفة التي تبني بيان PostgREST لكل مشروع:

تحملPGRST_DB_POOL / النسخة المتماثلةالنسخ المتماثلةاتصالات / مشروع استيقظ
مخصص (ممتاز، A1)10 (افتراضي PostgREST)220
مشترك (أسطول، مجاني/محترف/فريق)2 (Aurabase الافتراضي، منخفض)24
deploy/cnpg/tenant-postgrest.yaml (المستخرج الحقيقي، القيمة التي يستبدلها الموفر)yaml
# بصمة الاتصالات لكل نسخة متماثلة على الملف الأساسي.
env:
  - { name: PGRST_DB_POOL, value: "PGRST_DB_POOL_VALUE" }  # 10 (مخصص) أو 2 (مشترك)

على المستوى المخصص، تم تخفيف القيد: يمتلك المشروع مجموعة CNPG الخاصة به، وبالتالي max_connectionsخاص به، مع عدم وجود جيران إضافيين. على المستوى المشترك، تشترك العديد من المشاريع من نفس المؤسسة في مجموعة واحدة: وهذا هو السياق الذي يجعل ميزانية الاتصالات حاسمة، وهو ما تم تطويره في القسم التالي.

#
السقف الحقيقي

تحدد ميزانية الاتصالات عدد المستأجرين الذين يعملون في نفس الوقت

في مجموعة Postgres المشتركة، ليس إنتاجية HTTP هي التي تحدد عدد المشاريع النشطة في وقت واحد. هذا هو عدد الاتصالات التي تحتفظ بها مثيلات PostgREST مفتوحة على المستوى الأساسي، مقارنةً بـ max_connectionsالمتوفر.

تستمد Aurabase هذه الميزانية مباشرة من حدود المجموعة الفعلية، والتي تم تحديدها في fleet.rs: (max_connections − réserve superuser/CNPG − connexions réservées au pooler) ÷ connexions par projet éveillé، الطابق عند 1. الاحتياطي الثابت هو 10 اتصالات (المستخدم المتميز، ومدير مثيل CNPG، ومصدر المقاييس، وهامش المشرف المسؤول). بالنسبة للعيوب التي تم تسليمها (مجموعة من نسختين لكل نسخة متماثلة، أو نسختين متماثلتين، أو 4 اتصالات لكل مشروع تم تنشيطه)، يعطي الحساب ثلاث ميزانيات مختلفة اعتمادًا على مستوى تغيير حجم المجموعة.

ميزانية المشاريع النشطة في وقت واحد حسب المستوى، مجموعة Postgres المشتركةالمستوى المجاني: 5 مشاريع نشطة متزامنة (max_connections 50، Pooler 20). المستوى الاحترافي: 7 (max_connections 100، Pooler 60). مستوى الفريق: 10 (max_connections 200، Pooler 150). الصيغة مشتقة من كود Aurabase (fleet.rs::derive_wake_budget)، احتياطي ثابت من 10 اتصالات، 4 اتصالات لكل مشروع نشط.024681012مجاني (max_connections 50)5 مشاريعبرو (max_connections 100)7 مشاريعفريق (max_connections 200)10 مشاريع

المصدر: مشتق من fleet.rs::derive_wake_budget وwake_budget_for_org_plan، كود Aurabase، أعيد قراءته في 24 أغسطس 2026.

هذه الميزانية ليست حصة من المشاريع المملوكة: يمكن لمؤسسة team الاحتفاظ بـ 50 مشروعًا، معظمها خامل. هذا هو الحد الأقصى للتزامن : عدد المشاريع التي يمكنها الاحتفاظ باتصالات مفتوحة في نفس الوقت على المستوى الأساسي. لا يفشل التنبيه على الميزانية، بل يتم تأجيله حتى يعود مشروع شقيق إلى وضع السكون، ويتم التحقق منه في نفس الملف. تم توسيع موضوع تغيير الحجم max_connections نفسه في مقالتنا حول ضبط max_connectionsوالمفاضلة المخصصة/المتبادلة ككل في القاعدة المخصصة مقابل القاعدة المشتركة.

#
التكلفة الخفية

لماذا تفضل: count=exact يبطئ الاستعلام على جدول كبير

إن المطالبة بإجمالي دقيق يجبر Postgres على حساب الصفوف المرئية للنتيجة التي تمت تصفيتها مع كل استعلام، وهي تكلفة تنمو مع الجدول، وليست عملية مجانية.

لا يحتفظ PostgreSQL بأي عدادات صفوف مفهرسة خارج الصندوق. ضمن MVCC، تعتمد رؤية الصف على المعاملة التي تقرأه. لذلك يجب على COUNT(*) بالضبط زيارة الصفوف المرشحة بدلاً من قراءة قيمة محسوبة مسبقًا. يعد هذا قيدًا هيكليًا موثقًا جيدًا في نظام Postgres البيئي، بما في ذلك موردي التحليلات مثل ClickHouse، الذين يقارنون عداداتهم التقريبية بسلوك معاملات Postgres.

terminalbash
# باهظ الثمن على طاولة كبيرة: يفرض إجراء فحص MVCC للنتيجة التي تمت تصفيتها
curl "https://<gateway>/v1/db/<project_id>/orders?status=eq.paid" \
  -H "apikey: <clé>" -H "Prefer: count=exact"

# بدائل أقل تكلفة، موثقة بواسطة PostgREST
  -H "Prefer: count=planned"   # التقدير عبر المخطط
  -H "Prefer: count=estimated" # المخطط له بعد العتبة، بالضبط أدناه

يوثق PostgREST استراتيجيات العد الثلاثة هذه محليًا (postgrest.org، تم الوصول إليه في 24 أغسطس 2026). تضمن استراتيجية exact إجمالي سعر الفحص. planned يُرجع تقديرًا مجانيًا تقريبًا من مخطط الاستعلام. estimated يقوم بالتبديل تلقائيًا بين الاثنين بناءً على الحد. الاختيار ليس تجميليًا: فالترقيم الذي يتطلب count=exact على جدول يضم عدة ملايين من الصفوف يدفع ثمن هذا الفحص في كل صفحة، حتى عندما لا يراجع المستخدم الصفحة الأخيرة مطلقًا.

#
تقاس بالواقع

اقتطاع صفوف db-max غير مرئي بدون العد = بالضبط

يمكن أن يؤدي استخدام رأس الصف إلى اقتطاع استجابة PostgREST دون أي إشارة في النص أو الرؤوس، ما لم يتم طلب إجمالي دقيق بشكل صريح. لقد قمنا بقياسها في ظروف حقيقية على مثيل Aurabase مخصص، وهو أمر غير مفترض.

في جدول اختبار مكون من 10 صفوف مع PGRST_DB_MAX_ROWS=5، يعرض PostgREST v12.2.3 نفس رأس Content-Range تمامًا في حالتين مختلفتين تمامًا:

الاستعلامالخطوط المقدمةنطاق المحتوىميتا (أوراباسي)
?limit=50 (بدون إحصاء)5/10 حقيقي0-4/*{}
?limit=50&count=exact5/10 حقيقي0-4/10{المجموع: 10}

بدون count=exact، لا يمكن تمييز استجابة 5 صفوف عن جدول يحتوي بالفعل على 5 فقط: Content-Range: 0-4/* يصف الصفوف المقدمة، ولا يتم تطبيق الحد أبدًا. لا يظهر الحد الأقصى الفعلي في أي مكان في هذه الحالة، ويتم قياسه مباشرةً على مسار PostgREST الخاص بحزمة Aurabase SDK.

عواقب أي ترقيم صفحات على PostgREST

إذا قام نشر PostgREST بتعيين db-max-rows (إعدادات Aurabase الافتراضية هي 1000)، فقد يكون العميل الذي يقارن data.length بالحد المطلوب لاكتشاف صفحة كاملة مخطئًا. يظهر الخطأ بمجرد أن يكون سقف الخادم أقل من هذا الحد. الإشارة الوحيدة الموثوقة هي مقارنة عدد الخطوط المستلمة مع total التي يتم إرجاعها بواسطة count=exact، والتي تؤدي مباشرة إلى مقايضة التكلفة الموضحة في القسم السابق.

#
الكمون المؤجل

إعادة تحميل ذاكرة التخزين المؤقت للمخطط بعد الترحيل

يحتفظ PostgREST بمخطط Postgres في الذاكرة عند بدء التشغيل. بعد DDL (إنشاء جدول، إضافة عمود)، يجب إعادة تحميل ذاكرة التخزين المؤقت هذه قبل أن يستجيب المسار الجديد، وتكون عملية إعادة التحميل هذه غير متزامنة.

الكتابة التي تصل إلى هذه النافذة قد تتلقى 404 عابرًا (ذاكرة التخزين المؤقت لم يتم تحديثها بعد)، على الرغم من أن الجدول موجود بالفعل على جانب Postgres. تمتص بوابة Aurabase هذا من خلال حلقة إعادة محاولة محدودة، تم التحقق منها في postgrest_proxy.rs: ما يصل إلى 8 محاولات، وزيادة التراجع (250 مللي ثانية بالإضافة إلى 100 مللي ثانية لكل محاولة)، 3.5 ثانية تراكمية في أسوأ الحالات. تؤثر هذه الآلية فقط على عمليات الكتابة، ولا تقرأ أبدًا.

التفاصيل التي يوثقها الكود نفسه

لا تصدر البوابة أي إشارة إعادة تحميل: إنها تنتظر فقط. المشغل الحقيقي الوحيد هو pg_notify('pgrst', 'reload schema') الصادر عن خدمة قاعدة البيانات على مسار DDL. إذا نسي مسار الترحيل إرسال هذه الإشارة، فإن المحاولات الثماني تستنفد ذاكرة التخزين المؤقت التي لن تتغير أبدًا، وهو خطر موثق كما هو في تعليق الكود، وليس مخفيًا.

بالنسبة لنشر PostgREST المستضاف ذاتيًا، يتم تعميم الدرس. يجب أن يؤدي كل مسار DDL في تطبيقك إلى تشغيل عملية إعادة التحميل، عبر NOTIFY أو إشارة SIGUSR1 إلى العملية. وبخلاف ذلك، فإن الترحيل ينتج عنه ارتفاع في وقت الاستجابة p99 متخفيًا في شكل أخطاء متقطعة مباشرة بعد النشر.

#
ملخص

ما شرائح الهندسة المعمارية، وليس الإنتاجية الخام

تشترك القيود الأربعة الموثقة هنا في شيء واحد مشترك: لم يتم رؤية أي منها في اختبار إنتاجية HTTP معزول، ومع ذلك تحدد الأربعة جميعًا ما إذا كان نشر PostgREST يمتد إلى الإنتاج.

  • ميزانية الاتصال: تحدد عدد المستأجرين النشطين في نفس الوقت على مجموعة مشتركة، بغض النظر عن الإنتاجية لكل مستأجر.
  • تكلفة COUNT بالضبط: تنمو مع الجدول، وليس مع الحمل؛ تم تجاوزه بـ planned/estimated.
  • الاقتطاع الصامت: لا يزال من الممكن لغطاء الصف الذي تم تكوينه بشكل صحيح أن يقطع الترحيل ذي الأدوات السيئة.
  • إعادة تحميل المخطط: نافذة زمن الوصول بعد كل عملية ترحيل، تكون محدودة إذا كانت إشارة إعادة التحميل موصلة جيدًا، وغير محدودة بخلاف ذلك.

سواء كنت تختار بين PostgREST المستضافة ذاتيًا، أو طبقة GraphQL بنمط Hasura، أو واجهة برمجة التطبيقات المخصصة، فإن هذه المحاور الأربعة تعد نقطة مقارنة أفضل من شكل الطلب/الطلبات المعزولة. انظر مقارنتنا PostgREST vs Hasura vs custom API. إن اختيار المجمع الذي يقف أمام قاعدة البيانات الخاصة بك له نفس القدر من الأهمية: مقارنتنا PgBouncer vs Supavisor vs PgCat تفاصيل لماذا لا يمكن لـ PostgREST المرور عبر المجمع في وضع المعاملة.

#
الأسئلة المتداولة

الأسئلة الشائعة

هل PostgREST سريع بما يكفي للإنتاج على نطاق واسع؟+
PostgREST نفسها هي عملية خفيفة الوزن. في مثيلات Aurabase المخصصة، يتم تشغيل نسخة طبق الأصل باستخدام 50 إلى 250 مللي كور من وحدة المعالجة المركزية و64 إلى 128 ميجابايت من ذاكرة الوصول العشوائي، والتي تم التحقق منها في بيان Kubernetes الخاص بالمشروع. إن إنتاجية HTTP الخام لا تعد أبدًا العامل المقيد في الإنتاج. إنها ميزانية اتصال Postgres، وتكلفة COUNT بالضبط، وذاكرة التخزين المؤقت للمخطط التي تحدد ما إذا كان الأمر برمته يتوسع، وليس سرعة ثنائي PostgREST وحده.
كيف أعرف ما إذا كان استجابتي لـ PostgREST قد تم اقتطاعها بواسطة db-max-rows؟+
رأس Content-Range الذي تم إرجاعه بواسطة PostgREST لا يذكر هذا أبدًا. لا يمكن تمييز الاستجابة المحددة بـ 5 صفوف لكل صفوف db-max عن جدول يحتوي بالفعل على 5 فقط، ويتم قياسها في ظروف حقيقية على مثيل Aurabase مخصص. الطريقة الوحيدة الموثوقة لاكتشافها هي مقارنة عدد الأسطر المستلمة بالإجمالي الذي يتم إرجاعه بواسطة Prefer: count=exact، وبدون هذا الرأس يظل الاقتطاع غير مرئي.
هل يؤدي العدد الدقيق لـ COUNT دائمًا إلى إبطاء طلب PostgREST؟+
التفضيل: العد=الدقيق يفرض على Postgres حساب الصفوف المرئية للنتيجة التي تمت تصفيتها مع كل استعلام، وهي تكلفة تزيد مع حجم الجدول بسبب MVCC. لا يحتفظ Postgres بعداد صفوف مفهرس خارج الصندوق. يقدم PostgREST بديلين أقل تكلفة، العد = المخطط (التقدير عبر المجدول) والعد = المقدر (التبديل التلقائي بعد الحد الأدنى)، الموثق في وثائقه الرسمية.
ما عدد اتصالات Postgres التي يستهلكها PostgREST؟+
يعتمد ذلك كليًا على PGRST_DB_POOL مضروبًا في عدد النسخ المتماثلة. تم التحقق منه في كود Aurabase: يتم فتح مثيل مخصص (الطبقة المميزة) بشكل افتراضي 10 اتصالات لكل نسخة متماثلة، أو 20 في المجمل على نسختين متماثلتين. يقوم المستوى المشترك بخفض هذا التجمع طوعًا إلى 2 لكل نسخة متماثلة، أو 4 اتصالات لكل مشروع تم تنشيطه، لاستيعاب المزيد من المستأجرين بنفس ميزانية max_connections للمجموعة المشتركة.
هل هناك معيار PostgREST رسمي؟+
يحتفظ المشروع بمستودع مخصص، PostgREST/postgrest-benchmark على GitHub، والذي يتتبع اختلافات الإنتاجية من إصدار إلى إصدار بدلاً من نشر رقم تسويقي معزول. لم نقم بأدائها أو إعادة نشرها هنا. توثق هذه المقالة القيود المعمارية التي تم التحقق منها في الكود الخاص بنا وفي وثائق PostgREST الرسمية، وليس مقعدًا قمنا بإعادة إنتاجه بأنفسنا.
#
الاستنتاج

ماذا تتذكر

لا ينقطع PostgREST أبدًا تحت تحميل HTTP وحده: فبنيته بسيطة جدًا لذلك. ما يكسر الإنتاج هو ما يحيط به: كم عدد الاتصالات التي تظل نسخها المتماثلة مفتوحة، وكم التكلفة الإجمالية الدقيقة. ويتضمن ذلك أيضًا ما إذا كان الاقتطاع سيظل مرئيًا، ومدة استمرار النافذة بعد الترحيل.

هذه القيود الأربعة ليست خاصة بـ Aurabase: فهي تنطبق على أي نشر لـ PostgREST، مستضاف ذاتيًا أو مُدار. ما يوضحه هذا الرمز هو كيف أن النشر متعدد المستأجرين يجعلهم واضحين بدلاً من تركهم مفاجئين في الإنتاج.

هل أنت جاهز للنشر؟

الواجهة الخلفية الخاصة بك في خمس دقائق.

لا حاجة لبطاقة ائتمان · 500 ميجابايت مجانًا · 50000 MAU