SQL запрос к БД через WordPress в 46 раз дольше чем через phpmyadmin?

Ссылка скопирована
1 ответ

Вот такой запрос через $wpdb->get_col() выполняется 0,69s, а напрямую в phpmyadmin 0.0149s. В чем тут может быть дело?

SELECT DISTINCT tt.term_id FROM wp_term_relationships AS tr JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id JOIN wp_terms AS t ON tt.term_id = t.term_id WHERE tr.object_id IN ( SELECT p.ID FROM wp_posts AS p JOIN wp_term_relationships AS tr ON p.ID = tr.object_id JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id JOIN wp_terms AS t ON tt.term_id = t.term_id WHERE p.post_type = 'product' AND p.post_status = 'publish' AND tt.taxonomy = 'product_cat' AND t.term_id = '2961' ) AND tt.taxonomy LIKE 'pa_%';

SELECT DISTINCT tt.term_id FROM wp_term_relationships AS tr JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id JOIN wp_terms AS t ON tt.term_id = t.term_id WHERE tr.object_id IN ( SELECT p.ID FROM wp_posts AS p JOIN wp_term_relationships AS tr ON p.ID = tr.object_id JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id JOIN wp_terms AS t ON tt.term_id = t.term_id WHERE p.post_type = 'product' AND p.post_status = 'publish' AND tt.taxonomy = 'product_cat' AND t.term_id = '2961' ) AND tt.taxonomy LIKE 'pa_%';

Дополнительно:

Как минимум методы класса $wpdb делают значительно больше операций, чем сырой запрос в phpmyadmin
И каким методом вы время считали?

  • Запрос за меньшее время мог просто обработаться кэшем.
  • maksam07, microtime, а потом уже плагином query-monitor показывает тоже самое.
    Замер именно запроса, никаких обработок.

    SQL запрос к БД через WordPress в 46 раз дольше чем через phpmyadmin?

  • попробую по памяти угадать, что phpmyadmin втихую добавляет limit 20 к запросу. Соответственно, запрос и прерывается раньше.
  • Алексей Уколов, тогда при повторном запросе на сайте тоже бы из кэша брало, но по факту даже больше выдало

    SQL запрос к БД через WordPress в 46 раз дольше чем через phpmyadmin?

  • Melkij, Да, оказалось, что именно оно, спасибо) Выходит надо сидеть над запросом.
  • SQL запрос к БД через WordPress в 46 раз дольше чем через phpmyadmin?

    Во первых нужно нормально писать запрос, хотя бы для понимания что вы делаете:

    SELECT DISTINCT tt.term_id  FROM wp_term_relationships AS tr  JOIN wp_term_taxonomy AS tt  ON tr.term_taxonomy_id = tt.term_taxonomy_id  JOIN wp_terms AS t  ON tt.term_id = t.term_id  WHERE tr.object_id IN (    SELECT p.ID     FROM wp_posts AS p     JOIN wp_term_relationships AS tr     ON p.ID = tr.object_id     JOIN wp_term_taxonomy AS tt     ON tr.term_taxonomy_id = tt.term_taxonomy_id     JOIN wp_terms AS t     ON tt.term_id = t.term_id     WHERE p.post_type = 'product'     AND p.post_status = 'publish'     AND tt.taxonomy = 'product_cat'     AND t.term_id = '2961'  )  AND tt.taxonomy LIKE 'pa_%';

    SELECT DISTINCT tt.term_id FROM wp_term_relationships AS tr JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id JOIN wp_terms AS t ON tt.term_id = t.term_id WHERE tr.object_id IN ( SELECT p.ID FROM wp_posts AS p JOIN wp_term_relationships AS tr ON p.ID = tr.object_id JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id JOIN wp_terms AS t ON tt.term_id = t.term_id WHERE p.post_type = 'product' AND p.post_status = 'publish' AND tt.taxonomy = 'product_cat' AND t.term_id = '2961' ) AND tt.taxonomy LIKE 'pa_%';

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

    Ну и в третьих, запросы без лимита почти всегда будут медленными, так как бд вынуждена перебирать все таблицы перебором. Если же такой запрос необходим по каким то причинам, то стоит посмотреть что же происходит с запросом. Нужно в первую очередь сделать отдельно вложенный запрос, проверить как он работает, оптимизировать, а затем то же самое сделать с внешним. Так же неплохо прогнать эти запросы через explain, посмотреть каких индексов не хватает. Ну и первое на что стоит обратить внимание это tt.taxonomy LIKE 'pa_%', что само по себе затратно, и требует обязательного индекса.

    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Ольга Сеть Ответ

    Разница между phpMyAdmin и $wpdb->get_col() может быть из-за контекста выполнения, кэша, профилирования и того, что в WordPress вокруг запроса выполняется дополнительная логика. Но разница в 46 раз чаще всего указывает на сам SQL: подзапрос, JOIN по большим таблицам, LIKE 'pa_%' и отсутствие подходящих индексов.

    Первое, что нужно сделать, — выполнить EXPLAIN для запроса и посмотреть, какие индексы используются. В WordPress можно временно замерить только SQL:

    $start = microtime(true);
    $rows = $wpdb->get_col($sql);
    error_log('Query time: ' . (microtime(true) - $start));

    $start = microtime(true); $rows = $wpdb->get_col($sql); error_log('Query time: ' . (microtime(true) - $start));

    Ваш запрос можно упростить: сначала получить ID товаров из категории, затем получить атрибуты по этим товарам. Но для больших каталогов IN (SELECT ...) может быть тяжёлым. Иногда быстрее JOIN без вложенного подзапроса:

    SELECT DISTINCT tt2.term_id
    FROM wp_posts p
    JOIN wp_term_relationships tr1 ON p.ID = tr1.object_id
    JOIN wp_term_taxonomy tt1 ON tr1.term_taxonomy_id = tt1.term_taxonomy_id
    JOIN wp_term_relationships tr2 ON p.ID = tr2.object_id
    JOIN wp_term_taxonomy tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id
    WHERE p.post_type = 'product'
      AND p.post_status = 'publish'
      AND tt1.taxonomy = 'product_cat'
      AND tt1.term_id = 2961
      AND tt2.taxonomy LIKE 'pa_%';

    SELECT DISTINCT tt2.term_id FROM wp_posts p JOIN wp_term_relationships tr1 ON p.ID = tr1.object_id JOIN wp_term_taxonomy tt1 ON tr1.term_taxonomy_id = tt1.term_taxonomy_id JOIN wp_term_relationships tr2 ON p.ID = tr2.object_id JOIN wp_term_taxonomy tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id WHERE p.post_type = 'product' AND p.post_status = 'publish' AND tt1.taxonomy = 'product_cat' AND tt1.term_id = 2961 AND tt2.taxonomy LIKE 'pa_%';

    Также проверьте, не включён ли SAVEQUERIES, Query Monitor или другой дебаг, который замедляет WordPress. Для продакшена такие инструменты должны быть выключены. Если запрос нужен часто, кэшируйте результат в transient/object cache и обновляйте при изменении товаров, а не выполняйте тяжёлую выборку на каждом открытии страницы.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно