Мне нужно получить кучу постов с их метаданными. Конечно, вы не можете получить метаданные со стандартным запросом к сообщениям, поэтому вам, как правило, приходится делать a get_post_custom()
для каждого сообщения.
Я пытаюсь с одним пользовательским запросом, как это:
$results = $wpdb->get_results("
SELECT p.ID,
p.post_title,
pm1.meta_value AS first_field,
pm2.meta_value AS second_field,
pm3.meta_value AS third_field
FROM $wpdb->posts p LEFT JOIN $wpdb->postmeta pm1 ON (
pm1.post_id = p.ID AND
pm1.meta_key = 'first_field_key'
) LEFT JOIN $wpdb->postmeta pm2 ON (
pm2.post_id = p.ID AND
pm2.meta_key = 'second_field_key'
) LEFT JOIN $wpdb->postmeta pm3 ON (
pm3.post_id = p.ID AND
pm3.meta_key = 'third_field_key'
)
WHERE post_status = 'publish'
");
Кажется, работает. Он срабатывает, если вы используете любое из этих мета-полей таким образом, что для одного и того же поста можно использовать несколько мета-значений. Я не могу думать о соединении, чтобы сделать это.
Итак, вопрос 1: есть ли объединение, подзапрос или что-то еще, чтобы ввести мета-поля с несколькими значениями?
Но вопрос 2: оно того стоит? Сколько postmeta
объединений таблиц я должен добавить, прежде чем подход с двумя запросами станет предпочтительным? Я мог бы собрать все данные поста в одном запросе, затем собрать все соответствующие постметы в другом и объединить мета с данными поста в одном наборе результатов в PHP. Будет ли это быстрее, чем один очень сложный запрос SQL, если это вообще возможно?
Я всегда думаю: «Дайте как можно больше работы с базой данных». Не уверен в этом!
get_posts()
, тогдаget_post_meta()
для каждого из них? @MannyFleurmond, сложно найти точную информацию о встроенном кешировании WP, но AFAIK будет кешировать данные по запросу. Вызов серверу для получения этих данных является вызовом AJAX, и я не думаю, что что-то еще будет захватывать вещи до этого.Ответы:
Публикация метаинформации автоматически кэшируется в памяти для стандартного
WP_Query
(и основного запроса), если вы не указали этого специально, используяupdate_post_meta_cache
параметр.Поэтому вы не должны писать свои собственные запросы для этого.
Как мета-кеширование работает для обычных запросов:
Если для
update_post_meta_cache
параметраWP_Query
не установлено значение false, то после извлечения сообщений из БДupdate_post_caches()
будет вызвана функция, которая, в свою очередь, вызываетupdate_postmeta_cache()
.Эта
update_postmeta_cache()
функция является оберткой дляupdate_meta_cache()
, и она по сути вызывает простойSELECT
со всеми идентификаторами полученных сообщений. Это позволит получить все постметы для всех постов в запросе и сохранить эти данные в кеше объектов (используяwp_cache_add()
).Когда вы делаете что-то вроде этого
get_post_custom()
, он сначала проверяет этот кеш объекта. Так что на этом этапе не нужно делать дополнительные запросы для получения мета-поста. Если вы получили сообщение в aWP_Query
, то мета уже находится в памяти, и он получает его прямо оттуда.Преимущества здесь во много раз превосходят выполнение сложного запроса, но наибольшее преимущество заключается в использовании объектного кэша. Если вы используете постоянное решение для кэширования памяти, такое как XCache или memcached или APC или что-то в этом роде, и у вас есть плагин, который может привязать к нему объектный кэш (например, W3 Total Cache), то весь кэш объектов сохраняется в быстрой памяти уже. В этом случае для получения ваших данных требуется ноль запросов; это уже в памяти. Постоянное кэширование объектов во многих отношениях удивительно.
Другими словами, ваш запрос, вероятно, загружается и загружается медленнее, чем при использовании правильного запроса и простого решения для постоянной памяти. Используйте нормальное
WP_Query
. Сэкономь себе немного усилий.Дополнительно:
update_meta_cache()
умный, кстати. Он не будет получать метаинформацию для постов, в которых уже хранится метаинформация. Это не получает ту же самую мету дважды, в основном. Супер эффективный.Дополнительные дополнительные: «Дайте как можно больше работы с базой данных.» ... Нет, это Интернет. Применяются разные правила. В общем, вы всегда хотите дать как можно меньше работы с базой данных, если это возможно. Базы данных работают медленно или плохо настроены (если вы не настроили это специально, вы можете поспорить, что это правда). Часто они используются многими сайтами и в некоторой степени перегружены. Обычно у вас больше веб-серверов, чем баз данных. В общем, вы хотите просто и быстро вывести нужные данные из БД, а затем выполнить их сортировку с использованием кода на стороне веб-сервера. Как общий принцип, конечно, разные случаи все разные.
источник
Я бы порекомендовал сводный запрос. Используя ваш пример:
источник
Я сталкивался со случаем, когда хочу также быстро получить множество сообщений со связанной с ними метаинформацией. Мне нужно получить O (2000) сообщений.
Я попробовал это, используя предложение Отто - запустить WP_Query :: query для всех постов, а затем перебрать и запустить get_post_custom для каждого поста. В среднем это заняло около 3 секунд .
Затем я попробовал сводный запрос Итана (хотя мне не нравилось вручную запрашивать каждый мета-ключ, который меня интересовал). Мне все еще пришлось пройтись по всем извлеченным сообщениям, чтобы десериализовать meta_value. Это заняло в среднем около 1,3 секунды .
Затем я попытался использовать функцию GROUP_CONCAT и нашел лучший результат. Вот код:
Это заняло в среднем 0,7 секунды . Это примерно четверть времени решения WP get_post_custom () и около половины решения сводных запросов.
Может быть, это будет кому-то интересно.
источник
Я оказался в ситуации, когда мне нужно было выполнить эту задачу, чтобы в конечном итоге создать документ CSV, и в итоге я работал непосредственно с MySQL для этого. Мой код объединяет таблицы post и meta для получения информации о ценах woocommerce. Ранее опубликованное решение требовало, чтобы я использовал псевдонимы таблиц в sql для правильной работы.
Тем не менее, предупреждаю, что woocommerce создала более 300 тысяч строк в моей мета-таблице, поэтому она была очень большой и поэтому очень медленной.
источник
НЕТ SQL ВЕРСИИ:
Получите все сообщения и все их мета значения (метас) без SQL:
Допустим, у вас есть список идентификаторов записей, хранящихся в виде массива идентификаторов, что-то вроде
Теперь получение всех сообщений и всех метасов в одном запросе невозможно без использования хотя бы небольшого количества SQL, поэтому мы должны выполнить 2 запроса (все еще только 2):
1. Получить все сообщения (используя WP_Query )
(Не забудьте позвонить,
wp_reset_postdata();
если вы делаете «цикл» впоследствии;))2. Обновите мета кеш
Для получения метаданных просто используйте стандарт,
get_post_meta()
который, как указал @Otto:сначала заглядывает в кеш :)
Примечание: если вам на самом деле не нужны другие данные из постов (например, заголовок, контент, ...), вы можете сделать только 2. :-)
источник
используя форму решения trevor и модифицируя ее для работы с вложенным SQL. Это не проверено.
источник
Я столкнулся с проблемой мета полей с несколькими значениями. Проблема с самим WordPress. Посмотри в wp-includes / meta.php. Посмотрите на эту строку:
Проблема с оператором CAST. В запросе мета-значений переменная $ meta_type имеет значение CHAR. Я не знаю деталей о том, как CASTing значение в CHAR влияет на сериализованную строку, но чтобы исправить это, вы можете удалить приведение, чтобы SQL выглядел так:
Теперь, несмотря на то, что это работает, вы теряете внутренности WordPress, так что другие вещи могут сломаться, и это не постоянное исправление, при условии, что вам нужно обновить WordPress.
Я исправил это, скопировав SQL-запрос, сгенерированный WordPress для нужного мне мета-запроса, и затем написав PHP, чтобы добавить дополнительные операторы AND для нужных мне мета-значений, и использовать $ wpdb-> get_results ($ sql ) для окончательного вывода. Хаки, но это работает.
источник
get_meta_sql
фильтра, который следует за этой строкой, конечно, было бы предпочтительнее взлома основного кода.