سؤال

عند الترحيل عبر البيانات التي تأتي من قاعدة البيانات، فإنك تحتاج إلى معرفة عدد الصفحات الموجودة لعرض عناصر التحكم في الانتقال السريع للصفحة.

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

وهذا يبدو غير فعال.هل هناك طريقة أفضل لتحديد عدد النتائج التي كان سيتم إرجاعها من قبل LIMIT تم تطبيقه؟

أنا أستخدم PHP وPostgres.

هل كانت مفيدة؟

المحلول

SQL النقي

لقد تغيرت الأمور منذ عام 2008.يمكنك استخدام أ وظيفة النافذة للحصول على العدد الكامل والنتيجة المحدودة في استعلام واحد.(مقدمة مع بوستجري إس كيو إل 8.4 في عام 2009).

SELECT foo
     , count(*) OVER() AS full_count
FROM   bar
WHERE  <some condition>
ORDER  BY <some col>
LIMIT  <pagesize>
OFFSET <offset>

لاحظ أن هذا يمكن أن يكون أكثر تكلفة بكثير من دون العدد الإجمالي.يجب حساب جميع الصفوف، وقد لا يكون الاختصار المحتمل الذي يأخذ الصفوف العليا فقط من فهرس مطابق مفيدًا بعد الآن.
لا يهم كثيرًا مع الطاولات الصغيرة أو full_count <= OFFSET + LIMIT.يهم لأكبر بكثير full_count.

حالة الزاوية:متى OFFSET على الأقل كبير مثل عدد الصفوف من الاستعلام الأساسي، لا يوجد صف يتم إرجاع.لذلك تحصل أيضًا على لا full_count.البديل المحتمل:

النظر في تسلسل أحداث:

  1. WHERE جملة (و JOIN الشروط، ولكن ليس هنا) تصفية الصفوف المؤهلة من الجدول (الجداول) الأساسية.

    (GROUP BY وستذهب الوظائف المجمعة هنا.)

  2. يتم تطبيق وظائف النافذة مع الأخذ في الاعتبار جميع الصفوف المؤهلة (اعتمادًا على OVER جملة ومواصفات إطار الوظيفة).البسيط count(*) OVER() ويستند على جميع الصفوف.

  3. ORDER BY

    (DISTINCT أو DISTINCT ON سوف اذهب هنا.)

  4. LIMIT / OFFSET يتم تطبيقها بناءً على الترتيب المحدد لتحديد الصفوف المراد إرجاعها.

LIMIT / OFFSET يصبح غير فعال بشكل متزايد مع تزايد عدد الصفوف في الجدول.فكر في طرق بديلة إذا كنت بحاجة إلى أداء أفضل:

بدائل للحصول على العد النهائي

هناك طرق مختلفة تمامًا للحصول على عدد الصفوف المتأثرة (لا العدد الكامل من قبل OFFSET & LIMIT نفذت).لدى Postgres مسك دفاتر داخلي لعدد الصفوف التي تأثرت بأمر SQL الأخير.يمكن لبعض العملاء الوصول إلى تلك المعلومات أو حساب الصفوف بأنفسهم (مثل psql).

على سبيل المثال، يمكنك استرداد عدد الصفوف المتأثرة فيها com.plpgsql مباشرة بعد تنفيذ أمر SQL باستخدام:

GET DIAGNOSTICS integer_var = ROW_COUNT;

التفاصيل في الدليل.

أو يمكنك استخدام pg_num_rows في بي أتش بي.أو وظائف مماثلة في عملاء آخرين.

متعلق ب:

نصائح أخرى

وكما أصف على بلدي بلوق ، الخلية لديه ميزة تسمى SQL_CALC_FOUND_ROWS . هذا يزيل الحاجة إلى القيام الاستعلام مرتين، لكنه لا يزال يحتاج إلى القيام به الاستعلام في entireity لها، حتى إذا كان شرط الحد من شأنه أن يسمح لها أن يتوقف في وقت مبكر.

وبقدر ما أعرف، لا يوجد أي ميزة مشابهة لشبكة الإنترنت. شيء واحد لمشاهدة لعند القيام ترقيم الصفحات (الشيء الأكثر شيوعا التي تستخدم LIMIT IMHO): القيام ب "أوفست 1000 LIMIT 10" يعني أن DB لديها لجلب <م> على الأقل 1010 الصفوف، حتى إذا أنها تعطيك فقط 10. وهناك طريقة أكثر performant للالقيام به هو أن نتذكر قيمة الصف الذي يأمر بفضل الصف السابق (في 1000 في هذه الحالة) وإعادة كتابة الاستعلام مثل هذا: "... حيث order_row> value_of_1000_th LIMIT 10 ". ميزة هي أن "order_row" هو على الأرجح فهرسة (إن لم يكن، كنت قد ذهبت مشكلة). العيب يجري أنه إذا تم إضافة عناصر جديدة بين صفحة وجهات النظر، وهذا يمكن الحصول على القليل من التوافق (ولكن بعد ذلك مرة أخرى، قد لا تكون ملحوظة من قبل الزوار ويمكن أن يكون كسب الأداء الكبير).

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

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

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

إذا كنت تقوم بتشغيل الاستعلام COUNT لغرض البت في توفير البيانات للمستخدم أم لا (أي إذا كان هناك> X السجلات، تعيد خطأ)، تحتاج إلى عصا مع اقتراب COUNT.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top