Правда ли, что $wpdb->получение результатов в большинстве случаев быстрее, чем запрос WP?


На моей домашней странице у меня есть раздел, в котором я должен отобразить последние пять избранных сообщений, где избранное сообщение - это просто сообщение с настраиваемым полем is_featured, равным 1.

Я добился того, чего хотел, с помощью двух разных типов кодов:

Использование базы данных wpdb

<?php    
    $featuredPosts = $wpdb->get_results("
        SELECT ID, post_title FROM $wpdb->posts
        LEFT JOIN $wpdb->postmeta ON($wpdb->posts.ID = $wpdb->postmeta.post_id)
        WHERE $wpdb->postmeta.meta_key = 'is_featured'
        ORDER BY ID DESC LIMIT 5
    ");

    if ($featuredPosts)
    {
        $htmlOutput = '';                   

        foreach ($featuredPosts as $featPost)
            $htmlOutput .= '<br /><a href="'.get_permalink($featPost->ID).'">'.$featPost->post_title.'</a>';
    }

    echo $htmlOutput;
?>


Согласно плагину "Монитор запросов", этот запрос занимает 0,1 секунды и генерирует следующий SQL:

SELECT ID, post_title
FROM wp_posts LEFT JOIN wp_postmeta ON(wp_posts.ID = wp_postmeta.post_id)
WHERE wp_postmeta.meta_key = 'is_featured'
ORDER BY ID DESC
LIMIT 5


Использование родного Wordpress звонки

<?php                                                                       
    $featuredPostsRevised = new WP_Query
    (
        array
        (
            'meta_query' => array
            (
                array
                (
                    'key' => 'is_featured'
                )
            ) 
        ) 
    );  

    while($featuredPostsRevised->have_posts()) : $featuredPostsRevised->the_post();
?>
        <br />
        <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a>
<?php
    endwhile;
?>


Согласно плагину "Монитор запросов", этот запрос занимает 0,2 секунды и генерирует несколько более длинный SQL:

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta
ON (wp_posts.ID = wp_postmeta.post_id)
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private')
AND (wp_postmeta.meta_key = 'is_featured' )
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10

Мои вопросы таковы:

  1. Как я могу prepare() выполнить свой wpdb запрос? Я пытался, но не смог справиться из-за второго параметра.

  2. После использования prepare я прав, предполагая, что с точки зрения безопасности и производительности wpdb действительно является лучшим решением?

Author: Nicolai, 2014-06-26

1 answers

Как я могу подготовить() свой запрос wpdb? Я пытался, но не смог справиться из -за второго параметра.

Работа prepare() описана в Кодексе, вам нужен запрос с заполнителями и дополнительными аргументами для замены этих заполнителей. Если у вас нет заполнителей (поэтому в запросе нет переменных частей), вы можете использовать esc_sql, чтобы избежать SQL-инъекций, но это имеет смысл только тогда, когда запрос построен с использованием пользовательского ввода. Запрос в OP, полностью жестко закодирован, поэтому нет необходимости ни prepare(), ни esc_sql().

После использования prepare я прав, предполагая, что с точки зрения безопасности и производительности wpdb действительно является лучшим решением?

Короткий ответ: нет. WP_Query - это просто подход к запросам более высокого уровня, он создает строку запроса, а затем использует $wpdb для выполнения этого sql-запроса в базе данных.

Если вы посмотрите на 2 запроса в OP, то они разные, например, запрос выполнялся использование $wpdb не учитывает статус публикации, дату публикации или пароль для публикации, поэтому, если вы удалили, запланировали или закрыли публикации, с помощью первого запроса они будут показаны пользователям. Также в запросе не учитывается порядок результатов и некоторые другие вещи. Конечно, вы можете создать сложную строку запроса, которая учитывает все, а затем запустить ее с помощью $wpdb, у вас есть две возможности:

  1. пишите сложную жестко закодированную строку запроса каждый раз, когда вам нужен цикл: это действительно подавляющий и подверженный ошибкам
  2. напишите некоторый код, который обрабатывает запрос гибким способом: это будет очень сложно, и вы должны написать много кода, который уже обрабатывается ядром в WP_Query: это не имеет смысла.

Есть еще один важный фактор, который следует учитывать: WP_Query срабатывает довольно много фильтров и крючков действий , и тысячи плагинов и тем полагаются на них: запустив руководство $wpdb запрашивая циклы, вы сломаете много вещей.

Итак, если вам нужно запросить сообщения использовать WP_Query: несколько миллисекунд не стоят многих часов кода и разочарований. Используйте $wpdb только тогда, когда вам нужно выполнять запросы, не обрабатываемые ядром.

Стоит добавить @Tomjnowell Комментарий здесь:

Также следует иметь в виду, что WP_Query позволит вам воспользоваться множеством внутренних кэшей, хранящихся в WordPress, таких как получение сообщения один раз, если оно запрашивается во второй раз и т. Д. Если у вас есть 50 тысяч сообщений для запроса все сразу, вы, вероятно, должны использовать очередь заданий или сценарий командной строки для выполнения своей работы (если только у вас нет только десятков пользователей и много денег, которые можно потратить на сервере)

 7
Author: gmazzap, 2014-12-06 12:05:22