كيفية تحسين الإستعلامات إلى قاعدة البيانات على ووردبريس

كيفية تحسين الإستعلامات إلى قاعدة البيانات على ووردبريس

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

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

تحسين الاستعلامات على قاعدة البيانات

في ووردبريس لدينا عدة وسائل للتعامل مع قواعد البيانات لكن في غالب الحالات نستخدم WP_Query.

اقرأ أيضا: دروس ووردبريس من الصفر للمبتدئين بالفيديو

WP_Query هو عبارة عن كلاس يسمح لنا بجلب بيانات الصفحاتـ المقالات وأنواع المقالات المخصصة. افتراضيا، يتم تنفيذ 5 استعلامات تتضمن على سبيل المثال التخزين المؤقت لبيانات الميتا، عداد التصفح … الخ

دائما عند قيامك باستعلام عن طريق WP_Query خد بعين الاعتبار البارامترات التالية:

$args = [
         'no_found_rows' => true,
         'update_post_meta_cache' => false,
         'update_post_term_cache' => false,
         'posts_per_page' => 5
     ];
 $the_query = new WP_Query( $args );

no_found_rows يستعمل لعمل تصفح للبيانات العائدة من من WP_Query. في حالة عدم استخدامك للتصفح في الإستعلام الذي تقوم به، ببساطة قم بإعطائه القيمة true.

اقرأ أيضا: كيفية إضافة عضو ووردبريس جديد برمجيا

update_post_term_cache  هذا البارمتر اعطيه القيمة false لكيلا يتم تحديث التخزين المؤقت للتصنيفات والوسوم والتصنيفات المخصصة، هكذا توفر عليك استعلام آخر (فقط استخدمه إذا كنت لا تحتاج ترتيب المواضيع حسب التصنيف (taxonomy)!).

update_post_term_cache  هو نفس ما ذكرناه سابقا لكن هذه المرة يتعلق بالتخزين المؤقت الخاص بالخصائص الإضافية ( post meta)، ففي حالة عدم إدراج خصائص إضافية في الاستعلام يمكنك إعطائها القيمة false.

posts_per_page  هذا البرامتر يمكن من خلاله تحديد عدد المواضيع التي سيتم جلبها من قاعدة البيانات، ولجب كل المواضيع هناك من يضع 1- وهذا قد لا يكون مناسب إذا كان الموقع الذي تعمل عليه يتوفر على آلاف المقالات فمن الأفضل تحديد عدد المقالات الواجب جلبها لتخفيف العبء على الخادم، على سبيل المثال 'posts_per_page' => 500.

اقرأ أيضا: طريقة تعطيل WP Rest API

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

add_filter( 'posts_fields', 'posts_fields_custom_variable', 10, 2 );

function posts_fields_custom_variable( $fields, $query ) {

 global $wpdb;

 // Only if our custom variable is not false.
 if ( $query->get( 'limit_fields' ) ) {
 $fields = "$wpdb->posts.ID, $wpdb->posts.post_title";
 }

 return $fields;
}

$args = [
 'post_type'              => 'post',
 'no_found_rows'          => true,
 'update_post_meta_cache' => false,
 'update_post_term_cache' => false,
 'posts_per_page'         => 5,
 // Our custom variable.
 'limit_fields'           => true,
];

$the_query = new WP_Query( $args );

إذا كنا سنحتاج المعرف الوحيد فقط نستعمل البارمتر fields على هذا الشكل

$args = [
        'fields' => 'ids',
];

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

اقرأ أيضا: طريقة إضافة نجوم تقييم المقالات في ووردبريس

لكن للأسف هذه الدالة لا تستخدم افتراضيا في الاستعلامات المخصصة عبر WP_Query، ويمكننا إضافتها على هذا الشكل

<?php
$args = array(
  'post_type'             => 'post',
  'post_per_page'         => 5,
  'no_found_rows'         => true,
  'update_post_term_cache' => false,
  'suppress_filters'       => true,
);

$the_query= new WP_Query( $args );

if( $the_query->have_posts() ) {

  update_post_thumbnail_cache( $the_query);

  echo '<ul>';

  while( $the_query->have_posts() ) {
    $the_query->the_post();
    ?>
    <li>
      <h3><?php the_title(); ?></h3>
      <?php the_post_thumbnail( 'thumbnail' ); ?>
    </li>
    <?php
  }

  wp_reset_postdata();

  echo '</ul>';
}

لكن بدل وضع update_post_thumbnail_cache() داخل كل استعلام مخصص، يمكننا إضافة بارامتر مخصص نعطيه القيمة true في كل الاستعلامات التي ستحتوي على صور مصغرة.

add_filter( 'the_posts', 'sb_prime_post_thumbnails_cache', 10, 2 );
function sb_prime_post_thumbnails_cache( $posts, $query ) {

  if( ! $query->is_main_query() && $query->get( 'sb_upadate_post_thumbnail_cache' ) ) {
    update_post_thumbnail_cache( $query );
  }

  return $posts;
}

نستخدمه هكذا

اقرأ أيضا: عرض آخر المستخدمين المسجلين على ووردبريس

$args = [
    // Our custom parameter
    sb_upadate_post_thumbnail_cache' =>; true,
    ];
$latest_news = new WP_Query( $args );

علينا أن نعلم أيضا أن الدالة get_posts() تستخدم داخليا WP_Query وتحدد بعض البارامترات بقيمة مناسبة ك 'no_found_rows' => true، وكذلك تضع 'suppress_filters' => true وهذا يستبعد نتائج الاستعلام من نظام التخزين المؤقت الخاص بووردبريس، لهذا لا تنسى تمريره بالقيمة false في حالة استعمالك ل get_posts() ونفس الأمر مع wp_get_recent_posts() و get_children().

ولكي تكون استعلاماتنا أسرع يجب علينا تجنب قدر الإمكان البحث في جداول متعددة، على سبيل المثال استعلامات حسب تصنيفات (taxonomy) متعددة، استعلامات حسب خصائص إضافة (post meta) متعددة وكذلك الإبتعاد عن البارامترات من نوع __in و not_in كسبيل المثال category__in، category__not_in، post__not_in، tag__not_in … الخ

وفي حالة ضرورة استعمالها من الواجب عمل تخزين مؤقت للاستعلامات.

اقرأ أيضا: كيف أتعامل مع روابط الأرشيف في ووردبريس؟

التخزين المؤقت للإستعلامات في ووردبريس

ووردبريس يوفر لنا واجهتين برمجيتين تمكناننا من عمل تخزين مؤقت لاستعلاماتنا، الأولى WP Object Cache والأخرى Transients API.

الفرق بينها هو أن الأولى غير مستمرة (non-persistent) حيث يتم تخزين الاستعلام في الذاكرة العشوائية خلال مدة الاستعلام فقط، إذا أردت أن يتم عمل تخزين مستمر ( persistent caching ) عليك استخدام أحد الحلول ك W3 Total Cache، Memcached Object Cache، Redis Object Cache …

وهذا أفضل مثال للاستخدام WP Object Cache في WP_Query

اقرأ أيضا: إضافة هاشتاك تلقائيا للمواضيع المنشورة بواسطة Jetpack

$result = wp_cache_get( 'my_result' );
 
if ( false === $result ) {
    $args = array(
        'post_type' => 'post',
        'tax_query' => array(
            'relation' => 'OR',
            array(
                'taxonomy' => 'category',
                'field'    => 'slug',
                'terms'    => array( 'quotes' ),
            ),
            array(
                'relation' => 'AND',
                array(
                    'taxonomy' => 'post_format',
                    'field'    => 'slug',
                    'terms'    => array( 'post-format-quote' ),
                ),
                array(
                    'taxonomy' => 'category',
                    'field'    => 'slug',
                    'terms'    => array( 'wisdom' ),
                ),
            ),
        ),
    );
 
    $query = new WP_Query( $args );
 
    wp_cache_set( 'my_result', $query );
}

أما Transients API فتقوم بتخزين نتيجة الإستعلام في قاعدة البيانات، بالتحديد في جدول wp_options عوض تخزينه في الذاكرة، وبهذا يمكننا جلب نتيجة الاستعلام جاهزة في كل مرة وبالتالي تحسين كبير في الآداء وتخفيف العبء على الخادم.

مثال لاستخدام Transients API في WP_Query

$result = get_transient( 'my_result' );

if ( false === $result ) {
    $args = array(
        'post_type' => 'post',
        'tax_query' => array(
            'relation' => 'OR',
            array(
                'taxonomy' => 'category',
                'field'    => 'slug',
                'terms'    => array( 'quotes' ),
            ),
            array(
                'relation' => 'AND',
                array(
                    'taxonomy' => 'post_format',
                    'field'    => 'slug',
                    'terms'    => array( 'post-format-quote' ),
                ),
                array(
                    'taxonomy' => 'category',
                    'field'    => 'slug',
                    'terms'    => array( 'wisdom' ),
                ),
            ),
        ),
    );
 
    $query = new WP_Query( $args );
 
    set_transient( 'my_result', $query, HOUR_IN_SECONDS );
}

في هذا المثال قمنا بتحديد مدة صلاحية التخزين المؤقت في ساعة من الزمن، ووردبريس يوفر ستة ثوابت لتحديد المدة الزمنية لكن يمكنك استخدام نماذج أخرى من عندك إذا أردت

اقرأ أيضا: كيفية عرض مواضيع تابعة لنفس الكاتب في ووردبريس

MINUTE_IN_SECONDS = 60 (seconds)
HOUR_IN_SECONDS = 60 * MINUTE_IN_SECONDS
DAY_IN_SECONDS = 24 * HOUR_IN_SECONDS
WEEK_IN_SECONDS = 7 * DAY_IN_SECONDS
MONTH_IN_SECONDS = 30 * DAY_IN_SECONDS
YEAR_IN_SECONDS = 365 * DAY_IN_SECONDS

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

على سبيل المثال، هناك زر فايسبوك يعرض عدد الإعجابات لكل تدوينة وفي كل زيارة يتم الاتصال ب API فايسبوك لجلب عدد الإعجابات، في هذه الحالة يمكننا مثلا تخزين النتيجة العائدة من فايسبوك في قاعدة البيانات لمدة 5 دقائق على سبيل المثال أو مدة أطول إذا كنت تفضل ذلك، وهذا سيكون له مردود جد إجابي على سرعة تحميل الموقع إذا كان يستقبل عدد كبير من الزيارات.

الكود في هذه الحالة سيكون كالتالي:

اقرأ أيضا: كيفية إنشاء صفحات تلقائيا عند تنصيب قالب ووردبريس

$fb_count = get_transient('facebook_count');
 
if ( false === $fb_count ) {
    $return = wp_remote_get( 'http://graph.facebook.com/?id=http://www.mysie.com', array( 'timeout' => 10 ) );
    $json = json_decode($return["body"], true);
 
    $fb_count = isset($json["shares"]) ? intval($json["shares"]) : 0;
 
    set_transient('facebook_count', $fb_count, 5 * MINUTE_IN_SECONDS);
}

باستعمال الخطوات المذكورة في هذه التدوينة يمكننا تحسين اداء القالب أو الإضافة التي نعمل عليها بشكل جد ملحوظ، نحن نتكلم عن تحسين الأداء بأجزاء من الثانية، لن يلاحظ إذا كانت الزيارات قليلة لكن إذا كانت الزيارات بالآلاف أجزاء الثانية تتضاعف أيضا بالآلاف …

شكرا لك على الوصول إلى نهاية التدوينة 🙂

close

قم بالتسجيل على قائمتي البريدية لكي تكون من الأوائل في الحصول على تدوينات وشروحات حصرية

أنا لا أرسل أبدا البريد المزعج! اقرأ سياسة الخصوصية لمزيد من المعلومات.

13 تعليق

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

    1. وعليكم السلام أخي حسين، نسيت أن أذكر في التدوينة أن هذا الموضوع موجه بشكل أساسي للمطوين، إن شاء الله ستكون هناك شرحات لشتى المستويات 🙂

      تحياتي لك

      1. حيا الله بالاخ الغالي اخي لا بأس لا تخصص الدروس خلي المجال يكون مفتوح للجميع لان كل واحد يعرف مجاله و هو يختار بنفسه ما يناسبه في الموقع و المثل يقول تعب اليوم هو سلاح الغد و شكرا علي الرسالة
        والسلام

  2. الله يعطيك العافيه على المعلومات القيمة .

    هل تقصد خانة

    وهذا أفضل مثال للإستخدام WP Object Cache في WP_Query

    اقوم بوضعها داخل ملف الفنكشن للقالب ووردبريس وسوف يتم التخزين وكيفية تحديد الوقت للكاش للاستعلامات ؟

    اذا تكرمت تضع الكود كامل للفائدة .

    1. الله يعافيك أخي عمر

      المثال يظهر كيفة تطبيق WP Object Cache على استعلام مخصص بواسطة [code lang=”php” inline=”true”]WP_Query[/code]، يعني أن الكود يتغير حسب الإستعلام الذي تريد عمله ولا يمكن إعطاء كود معيّن لووضه في ملف [code lang=”php” inline=”true”]functions.php[/code] …

      تحياتي.

اترك تعليقًا

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *