🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

كيفية تنفيذ ترقيم الصفحات في REST API: دليل 2026 الكامل

⏱️2 min read  ·  303 words

ترقيم الصفحات يعد أمرًا ضروريًا لأي واجهة برمجة تطبيقات تُرجع القوائم – وبدون ذلك، يؤدي الاستعلام الذي يعرض ملايين الصفوف إلى تعطل الخادم الخاص بك وإرهاق العملاء. ولكن هناك العديد من إستراتيجيات ترقيم الصفحات ذات خصائص أداء مختلفة جدًا. يغطي هذا الدليل كل هذه العناصر ومتى يتم استخدام كل منها.

لماذا يهم ترقيم الصفحات

  • الأداء: إرجاع كافة الصفوف بطيء ويستهلك الكثير من الذاكرة
  • عرض النطاق الترددي: لا يحتاج العملاء إلى آلاف السجلات في وقت واحد
  • تحميل قاعدة البيانات: الاستعلامات المحددة تحمي قاعدة البيانات الخاصة بك
  • تجربة المستخدم: تحميل البيانات في الصفحات أسرع وأنظف

الإستراتيجية 1: ترقيم الصفحات الإزاحة/الحدودية (بسيط)

-- The classic approach: OFFSET and LIMIT
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;   -- page 3 (skip 40, take 20)
// Express endpoint
app.get('/products', async (req, res) => {
  const page  = parseInt(req.query.page)  || 1;
  const limit = parseInt(req.query.limit) || 20;
  const offset = (page - 1) * limit;

  const products = await db.query(
    'SELECT * FROM products ORDER BY created_at DESC LIMIT $1 OFFSET $2',
    [limit, offset]
  );
  const total = await db.query('SELECT COUNT(*) FROM products');

  res.json({
    data: products.rows,
    pagination: {
      page,
      limit,
      total: total.rows[0].count,
      totalPages: Math.ceil(total.rows[0].count / limit),
    }
  });
});

الايجابيات: بسيطة، وتدعم القفز إلى أي صفحة، ويظهر العدد الإجمالي.
السلبيات: بطيء في الإزاحات الكبيرة (لا تزال قاعدة البيانات تفحص جميع الصفوف التي تم تخطيها)، ويمكن أن تتغير النتائج إذا تغيرت البيانات بين الطلبات.

الإستراتيجية 2: ترقيم صفحات المؤشر (قابل للتطوير)

بدلاً من الإزاحة، استخدم “المؤشر” (عادةً معرف العنصر الأخير أو الطابع الزمني) لجلب الصفحة التالية. يؤدي هذا إلى توسيع نطاق ملايين الصفوف لأن قاعدة البيانات تنتقل مباشرة إلى الموضع:

-- Fetch items AFTER a cursor (much faster than large OFFSET)
SELECT * FROM products
WHERE created_at < $1   -- cursor = last item's created_at
ORDER BY created_at DESC
LIMIT 20;
app.get('/products', async (req, res) => {
  const limit  = parseInt(req.query.limit) || 20;
  const cursor = req.query.cursor;   // the last item's timestamp/id

  let query, params;
  if (cursor) {
    query = 'SELECT * FROM products WHERE created_at < $1 ORDER BY created_at DESC LIMIT $2';
    params = [cursor, limit + 1];   // fetch one extra to check for more
  } else {
    query = 'SELECT * FROM products ORDER BY created_at DESC LIMIT $1';
    params = [limit + 1];
  }

  const result = await db.query(query, params);
  const hasMore = result.rows.length > limit;
  const items = hasMore ? result.rows.slice(0, limit) : result.rows;
  const nextCursor = hasMore ? items[items.length - 1].created_at : null;

  res.json({
    data: items,
    pagination: { nextCursor, hasMore }
  });
});

الايجابيات: سريع على أي نطاق (لا يوجد مسح للأوفست)، ونتائج مستقرة حتى مع تغير البيانات.
السلبيات: لا يمكن الانتقال إلى صفحات عشوائية، ولا يوجد عدد إجمالي للصفحات، وهو أكثر تعقيدًا بعض الشيء.

الإستراتيجية 3: ترقيم الصفحات بين مجموعة المفاتيح (أفضل أداء)

-- Keyset uses a unique, ordered column (often id) for precise positioning
SELECT * FROM products
WHERE (created_at, id) < ($1, $2)   -- composite cursor handles ties
ORDER BY created_at DESC, id DESC
LIMIT 20;

يستخدم ترقيم الصفحات في مجموعة المفاتيح مؤشرًا مركبًا (مثل create_at + id) للتعامل مع الصفوف ذات الطوابع الزمنية المتطابقة. إنه النهج الأكثر قوة عالي الأداء، والذي تستخدمه واجهات برمجة التطبيقات (API) التي تخدم مجموعات بيانات ضخمة.

المقارنة: أيهما يجب استخدامه

استراتيجية الأفضل لـ مقياس
الإزاحة/الحد مجموعات البيانات الصغيرة، وواجهات المستخدم الإدارية التي تحتاج إلى أرقام الصفحات الصغيرة والمتوسطة
المؤشر خلاصات، تمرير لا نهائي، مجموعات بيانات كبيرة كبير
مجموعة المفاتيح مجموعات بيانات ضخمة واحتياجات عالية الأداء كبير جداً

تنسيق الاستجابة المتسق

// Offset-based response
{
  "data": [ /* items */ ],
  "pagination": {
    "page": 3,
    "limit": 20,
    "total": 1543,
    "totalPages": 78
  }
}

// Cursor-based response
{
  "data": [ /* items */ ],
  "pagination": {
    "nextCursor": "2026-07-20T10:30:00Z",
    "hasMore": true
  }
}

نصائح للأداء

  • قم بفهرسة عمود الفرز الخاص بك: تحتاج استعلامات ترقيم الصفحات إلى فهرس في العمود ORDER BY، أو أنها بطيئة
  • تجنب COUNT(*) في الجداول الضخمة: يعد حساب جميع الصفوف أمرًا مكلفًا – حيث يتجنب ترقيم الصفحات للمؤشر الحاجة إلى العدد الإجمالي
  • سقف الحد: فرض الحد الأقصى لحجم الصفحة (على سبيل المثال، 100) حتى لا يتمكن العملاء من طلب كل شيء
  • استخدم المؤشر/مجموعة المفاتيح للبيانات الكبيرة: يتدهور ترقيم الصفحات في الإزاحة بشكل سيئ عند الإزاحات الكبيرة — تقوم قاعدة البيانات بفحص جميع الصفوف التي تم تخطيها
  • حد الجلب +1 لاكتشاف “hasMore”: اطلب صفًا إضافيًا لمعرفة ما إذا كانت هناك صفحة تالية بدون عدد منفصل

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

س: إزاحة أو ترقيم صفحات المؤشر؟
ج: إزاحة مجموعات البيانات الصغيرة وواجهات المستخدم الإدارية التي تحتاج إلى أرقام الصفحات والانتقال إلى صفحات محددة. مؤشر للخلاصات والتمرير اللانهائي ومجموعات البيانات الكبيرة حيث يكون الأداء والاستقرار مهمًا. يتغير حجم المؤشر بشكل أفضل بكثير ولكن لا يمكنه الانتقال إلى الصفحات العشوائية.

س: لماذا يكون ترقيم الصفحات الخاص بي بطيئًا؟
A: OFFSET 100000 يجعل قاعدة البيانات تفحص وتتجاهل 100000 صف قبل إرجاع صفحتك – ببطء متزايد مع نمو الإزاحة. قم بالتبديل إلى المؤشر أو ترقيم الصفحات لمجموعة المفاتيح، والتي تنتقل مباشرة إلى الموضع باستخدام عمود مفهرس.

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

س: هل أحتاج إلى إرجاع العدد الإجمالي؟
ج: بالنسبة إلى ترقيم الصفحات الذي يحتوي على أرقام الصفحات، عادةً ما يكون نعم. لكن COUNT(*) على الطاولات الكبيرة باهظ الثمن. يتجنبه ترقيم الصفحات للمؤشر تمامًا (فقط “hasMore”). إذا كنت بحاجة إلى أعداد تقريبية على جداول ضخمة، ففكر في الأعداد المخزنة مؤقتًا أو المقدرة.

س: ما هو الحجم الافتراضي الجيد والحد الأقصى لحجم الصفحة؟
ج: 20-25 كإعداد افتراضي، بحد أقصى 100 مفروض من جانب الخادم. وهذا يوازن بين حجم الاستجابة وعدد الطلبات. حدد دائمًا الحد الأقصى حتى لا يتمكن العملاء من طلب بيانات غير محدودة باستخدام?limit=999999.

الخلاصة

يعد ترقيم الصفحات الصحيح أمرًا ضروريًا لأي واجهة برمجة تطبيقات لإرجاع القائمة. استخدمالإزاحة/الحد لمجموعات البيانات الصغيرة وواجهات المستخدم الإدارية التي تحتاج إلى أرقام الصفحات، وترقيم الصفحات للمؤشر للخلاصات ومجموعات البيانات الكبيرة، وترقيم الصفحات لمجموعة المفاتيح لتلبية الاحتياجات الضخمة عالية الأداء. الإزاحة هي الأبسط ولكنها تتحلل عند الإزاحات الكبيرة؛ يتغير حجم المؤشر ومجموعة المفاتيح إلى ملايين الصفوف من خلال القفز مباشرة إلى الموضع باستخدام الأعمدة المفهرسة. قم بفهرسة عمود الفرز، وتحديد حجم الصفحة، وجلب الحد +1 لاكتشاف المزيد من الصفحات، وإرجاع تنسيق استجابة ثابت. يؤدي اختيار الإستراتيجية المناسبة لمقياس البيانات الخاص بك إلى الحفاظ على سرعة واجهة برمجة التطبيقات الخاصة بك وصحة قاعدة بياناتك مع نمو بياناتك.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা