SQL запрос к БД через WordPress в 46 раз дольше чем через phpmyadmin?
Вот такой запрос через $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
И каким методом вы время считали?
Замер именно запроса, никаких обработок.
Во первых нужно нормально писать запрос, хотя бы для понимания что вы делаете:
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_%', что само по себе затратно, и требует обязательного индекса.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос



Разница между 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));
Ваш запрос можно упростить: сначала получить 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_%';
Также проверьте, не включён ли
SAVEQUERIES, Query Monitor или другой дебаг, который замедляет WordPress. Для продакшена такие инструменты должны быть выключены. Если запрос нужен часто, кэшируйте результат в transient/object cache и обновляйте при изменении товаров, а не выполняйте тяжёлую выборку на каждом открытии страницы.