7logic
Forum Replies Created
-
Forum: Plugins
In reply to: [RSS for Yandex Turbo] Проблема с производительностью SQLЗдравствуйте!
Технически ограничение по дате имеет смысл в некоторых ситуациях, т.к. кардинально меняет план запроса, что сказывается положительно на времени выполнения SQL.
В нашем примере с wp_postmeta 25 млн записей при запросе всего 40 записей для фида Яндекс.Турбо время выполнения SQL занимало 160 секунд. После добавления фильтра по дате – порядка 10 секунд.
Добавление фильтра даты для запросов Яндекс.Дзен также изменит план выполнения запроса: БД не придётся собирать огромную таблицу, сохранять её на диск, чтобы потом из неё выбрать 20-50 записей. При наложении даты объем данных, с которыми БД будет работать, в разы станет меньше (дата есть в индексе). Согласен, что это больше похоже на хак, но это рабочее решение.
есть предложения, как еще улучшить wp_query, не используя ограничение по дате?
На данный момент проблема существует непосредственно в ядре WP в коде WP_Query при использовании meta_query с логикой OR при наличии большой таблицы wp_postmeta (тикет 24093, тикет 30044).
Альтернативным решением может быть отказ от условия OR для проверки ytrssenabled_meta_value:
array('key' => 'ytrssenabled_meta_value', 'compare' => 'NOT EXISTS',),
В этом случае WP не будет генерировать много JOIN в SQL, и запрос будет работать быстрее. Для того, чтобы это работало, можно предусмотреть добавление отсутствующих в wp_postmeta значений ytrssenabled_meta_value при активации плагина.Ещё одним из вариантов может быть кастомный код для формирования SQL вместо WP_Query.
Самым лучшим вариантом я вижу написание патча для ядра WP в части оптимизации SQL при использовании проверки NOT EXISTS и проверки значения для одного ключа (релевантный тикет):
'meta_query' => array( 'relation' => 'OR', array('key' => 'ytrssenabled_meta_value', 'compare' => 'NOT EXISTS',), array('key' => 'ytrssenabled_meta_value', 'value' => 'yes', 'compare' => '!=',), )В этом случае не придётся изменять код плагина, а WP_Query будет генерировать более оптимальный SQL. Наша команда попробует поучаствовать в этом процессе. Если сделаем патч, и он войдёт в новую сборку WP, сделаю апдейт в этой ветке.
Forum: Plugins
In reply to: [RSS for Yandex Turbo] Проблема с производительностью SQLДобрый день!
Дело в том, что WP_Query – всего лишь инструмент в руках разработчика, и его важно правильно использовать. Мы поддерживаем доработку плагинов и не хотим плодить хаки в проектах для решения проблем. Я углубился в проблему, разобрался и хочу предложить вам решение. Буду признателен, если найдёте время для анализа предложенного решения и доработки плагина. Кстати, вы поддерживаете pull request через github?
Предлагаю добавить в настройки плагина фильтр по дате создания записей – “Выгружать записи не старше %s”. Например, можно добавить список с вариантами 1 год, 6 мес, 3 мес, 1 мес, 2 нед. При включении этого фильтра добавлять date_query в args[] для WPQuery. Подобная настройка была бы полезна и для плагина RSS for Yandex Zen.
Ниже я опишу технические детали, почему это решение работает.
Указанный в тикете запрос относится к следующему участку кода:
$args = array( 'paged' => $paged, 'ignore_sticky_posts' => 1, 'post_type' => $yttype, 'post_status' => 'publish', 'posts_per_page' => $ytrazbnumber, 'tax_query' => $tax_query, 'meta_query' => array( 'relation' => 'OR', array('key' => 'ytrssenabled_meta_value', 'compare' => 'NOT EXISTS',), array('key' => 'ytrssenabled_meta_value', 'value' => 'yes', 'compare' => '!=',), ) ); $args = apply_filters( 'yturbo_query_args', $args ); $query = new WP_Query( $args );Аналогичная проблема есть в плагине RSS for Yandex Zen на следующем участке кода:
$args = array('ignore_sticky_posts' => 1, 'post_type' => $yztype, 'post_status' => 'publish', 'posts_per_page' => $yznumber,'tax_query' => $tax_query, 'meta_query' => array('relation' => 'OR', array('key' => 'yzrssenabled_meta_value', 'compare' => 'NOT EXISTS',), array('key' => 'yzrssenabled_meta_value', 'value' => 'yes', 'compare' => '!=',),)); $args_alt = apply_filters( 'yzen_query_args', $args, 8 ); if (isset($args_alt) && is_array($args_alt)) $args = $args_alt; $query = new WP_Query( $args );Указанный выше порядок аргументов заставляет WP генерировать неоптимальный SQL-код с несколькими LEFT JOIN, что вызывает сборку временной таблицы, которая на больших БД может не влезать в память и начинает сбрасываться на диск. Проблема не новая, проявляется на запросах WPQuery, где включён meta_query с логикой OR, проблема описана в тикетах WP 6-летней давности:
https://core.trac.wordpress.org/ticket/24093
https://core.trac.wordpress.org/ticket/30044Оптимизация в ядре так и не была проведена, решение кроется в декомпозиции запроса с применением подзапросов или наложении ограничений по индексу, чтобы изменить план запроса.
На мой взгляд, самым правильным решением является наложение фильтра по полю post_date, которое есть в индексе. В нашем примере ограничим выборку записей 1 месяцем, получается такой запрос:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) LEFT JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'ytrssenabled_meta_value' ) LEFT JOIN wp_postmeta AS mt1 ON ( wp_posts.ID = mt1.post_id ) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (1,4,16,178,591,1113,1465) ) AND ( wp_postmeta.post_id IS NULL OR ( mt1.meta_key = 'ytrssenabled_meta_value' AND mt1.meta_value != 'yes' ) ) AND wp_posts.post_date >= '2020-07-18' and wp_posts.post_type = 'post' AND ((wp_posts.post_status = 'publish')) GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 40План выполнения запроса изменился кардинально:
+----+-------------+-----------------------+------------+-------+---------------------------------------------------------------------------------------+------------------+---------+---------------------------+------+----------+-----------------------------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------------------+------------+-------+---------------------------------------------------------------------------------------+------------------+---------+---------------------------+------+----------+-----------------------------------------------------------+ | 1 | SIMPLE | wp_posts | NULL | range | PRIMARY,type_status_date,type_status_modified_gmt,status_type_password1_date_modified | type_status_date | 169 | NULL | 719 | 100.00 | Using where; Using index; Using temporary; Using filesort | | 1 | SIMPLE | wp_term_relationships | NULL | ref | PRIMARY,term_taxonomy_id | PRIMARY | 8 | u100007_ramns.wp_posts.ID | 2 | 34.26 | Using where; Using index | | 1 | SIMPLE | wp_postmeta | NULL | ref | post_id,meta_key | post_id | 8 | u100007_ramns.wp_posts.ID | 232 | 100.00 | Using where | | 1 | SIMPLE | mt1 | NULL | ref | post_id | post_id | 8 | u100007_ramns.wp_posts.ID | 232 | 100.00 | Using where | +----+-------------+-----------------------+------------+-------+---------------------------------------------------------------------------------------+------------------+---------+---------------------------+------+----------+-----------------------------------------------------------+ 4 rows in set, 1 warning (0.00 sec)Такой запрос выполняется в десятки раз быстрее, а результат выполнения запроса тот же (в проекте добавляются десятки записей в день).
Резюмируя, хочу добавить, что ту же логику возможно реализовать через встроенные в код плагина фильтры yturbo_query_args и yzen_query_args (для плагина RSS for Yandex Zen), но добавление фильтра по дате в настройки плагина видится наиболее правильным решением. Подобный фильтр поможет избежать проблем производительности в проектах с относительно большим объёмом данных.
Спасибо за внимание.
С уважением,
Александр Зайцев
/* moderator note: пожалуйста, не используйте подписи на форумах. */Forum: Plugins
In reply to: [Gutenberg] after 5.3 update, editing problemsAlso have a serious problems with Gutenberg after update WP to 5.3
Galleries with using custom js and css was crashed after update because it changed their DOM structure ( and broken css ad js ) It was very bad idea 🙁 it is too big torubles for minor update 🙁