Title: 7logic's Replies | WordPress.org

---

# 7logic

  [  ](https://wordpress.org/support/users/7logic/)

 *   [Profile](https://wordpress.org/support/users/7logic/)
 *   [Topics Started](https://wordpress.org/support/users/7logic/topics/)
 *   [Replies Created](https://wordpress.org/support/users/7logic/replies/)
 *   [Reviews Written](https://wordpress.org/support/users/7logic/reviews/)
 *   [Topics Replied To](https://wordpress.org/support/users/7logic/replied-to/)
 *   [Engagements](https://wordpress.org/support/users/7logic/engagements/)
 *   [Favorites](https://wordpress.org/support/users/7logic/favorites/)

 Search replies:

## Forum Replies Created

Viewing 3 replies - 1 through 3 (of 3 total)

 *   Forum: [Plugins](https://wordpress.org/support/forum/plugins-and-hacks/)
    In
   reply to: [[RSS for Yandex Turbo] Проблема с производительностью SQL](https://wordpress.org/support/topic/%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%d0%b0-%d1%81-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d1%81%d1%82%d1%8c%d1%8e-sql/)
 *  Thread Starter [7logic](https://wordpress.org/support/users/7logic/)
 * (@7logic)
 * [5 years, 8 months ago](https://wordpress.org/support/topic/%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%d0%b0-%d1%81-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d1%81%d1%82%d1%8c%d1%8e-sql/#post-13328430)
 * Здравствуйте!
 * Технически ограничение по дате имеет смысл в некоторых ситуациях, т.к. кардинально
   меняет план запроса, что сказывается положительно на времени выполнения SQL.
 * В нашем примере с wp_postmeta 25 млн записей при запросе всего 40 записей для
   фида Яндекс.Турбо время выполнения SQL занимало 160 секунд. После добавления 
   фильтра по дате – порядка 10 секунд.
 * Добавление фильтра даты для запросов Яндекс.Дзен также изменит план выполнения
   запроса: БД не придётся собирать огромную таблицу, сохранять её на диск, чтобы
   потом из неё выбрать 20-50 записей. При наложении даты объем данных, с которыми
   БД будет работать, в разы станет меньше (дата есть в индексе). Согласен, что 
   это больше похоже на хак, но это рабочее решение.
 * > есть предложения, как еще улучшить wp_query, не используя ограничение по дате?
 * На данный момент проблема существует непосредственно в ядре WP в коде WP_Query
   при использовании meta_query с логикой OR при наличии большой таблицы wp_postmeta(
   [тикет 24093](https://core.trac.wordpress.org/ticket/24093), [тикет 30044](https://core.trac.wordpress.org/ticket/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 и проверки значения для одного ключа(
   [релевантный тикет](https://core.trac.wordpress.org/ticket/38173)):
 *     ```
           '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](https://wordpress.org/support/forum/plugins-and-hacks/)
    In
   reply to: [[RSS for Yandex Turbo] Проблема с производительностью SQL](https://wordpress.org/support/topic/%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%d0%b0-%d1%81-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d1%81%d1%82%d1%8c%d1%8e-sql/)
 *  Thread Starter [7logic](https://wordpress.org/support/users/7logic/)
 * (@7logic)
 * [5 years, 9 months ago](https://wordpress.org/support/topic/%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%d0%b0-%d1%81-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d1%81%d1%82%d1%8c%d1%8e-sql/#post-13272663)
 * Добрый день!
 * Дело в том, что WP_Query – всего лишь инструмент в руках разработчика, и его 
   важно правильно использовать. Мы поддерживаем доработку плагинов и не хотим плодить
   хаки в проектах для решения проблем. Я углубился в проблему, разобрался и хочу
   предложить вам решение. Буду признателен, если найдёте время для анализа предложенного
   решения и доработки плагина. Кстати, вы поддерживаете pull request через github?
 * Предлагаю добавить в настройки плагина фильтр по дате создания записей – “Выгружать
   записи не старше %s”. Например, можно добавить список с вариантами 1 год, 6 мес,
   3 мес, 1 мес, 2 нед. При включении этого фильтра добавлять [date_query в args[] для WPQuery](https://developer.wordpress.org/reference/classes/wp_query/#date-parameters).
   Подобная настройка была бы полезна и для плагина [RSS for Yandex Zen](https://wordpress.org/plugins/rss-for-yandex-zen/).
 * Ниже я опишу технические детали, почему это решение работает.
 * Указанный в тикете запрос относится к [следующему участку кода](https://plugins.trac.wordpress.org/browser/rss-for-yandex-turbo/trunk/rss-for-yandex-turbo.php#L2597):
 *     ```
       $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](https://wordpress.org/plugins/rss-for-yandex-zen/)
   на [следующем участке кода](https://plugins.trac.wordpress.org/browser/rss-for-yandex-zen/trunk/rss-for-yandex-zen.php#L806):
 *     ```
       $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/24093)
   [https://core.trac.wordpress.org/ticket/30044](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](https://wordpress.org/plugins/rss-for-yandex-zen/)), но 
   добавление фильтра по дате в настройки плагина видится наиболее правильным решением.
   Подобный фильтр поможет избежать проблем производительности в проектах с относительно
   большим объёмом данных.
 * Спасибо за внимание.
 * С уважением,
    Александр Зайцев _/* moderator note: пожалуйста, не используйте
   подписи на форумах. */_
    -  This reply was modified 5 years, 9 months ago by [Yui](https://wordpress.org/support/users/fierevere/).
    -  This reply was modified 5 years, 9 months ago by [Yui](https://wordpress.org/support/users/fierevere/).
      Reason: drop signature part
 *   Forum: [Plugins](https://wordpress.org/support/forum/plugins-and-hacks/)
    In
   reply to: [[Gutenberg] after 5.3 update, editing problems](https://wordpress.org/support/topic/after-5-3-update-editing-problems/)
 *  [7logic](https://wordpress.org/support/users/7logic/)
 * (@7logic)
 * [6 years, 5 months ago](https://wordpress.org/support/topic/after-5-3-update-editing-problems/#post-12217281)
 * Also 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 🙁

Viewing 3 replies - 1 through 3 (of 3 total)