@maratmd

Как ускорить sql запрос?

Есть запрос (работает медленно), как я понимаю он скорее всего написан не правильно, и долго обрабатывается. Читал что для ускорения нужно использовать UNION вместо OR. Вот запрос
SELECT t1.sum_za_zakazy AS sum_za_zakazy,  t2 .......


FROM ( SELECT COALESCE (sum(v2.meta_value),0) AS sum_za_zakazy
       FROM wp_posts
       JOIN wp_postmeta v1 ON (wp_posts.ID = v1.post_id)
	   JOIN wp_postmeta v2 ON (wp_posts.ID = v2.post_id)
	   JOIN wp_postmeta v3 ON (wp_posts.ID = v3.post_id)
WHERE
((v1.meta_key = 'id_shvei_1' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'summa_shvei_1' AND v3.meta_key = 'shveia-1-data' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_shvei_2' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'summa_shvei_2' AND v3.meta_key = 'shveia-2-data' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_shvei_3' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'summa_shvei_3' AND v3.meta_key = 'shveia-3-data' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_razborshhika_1' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'summa_razborshhika_1' AND v3.meta_key = 'razborshchik-1-data' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_razborshhika_2' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'summa_razborshhika_2' AND v3.meta_key = 'razborshchik-2-data' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_sborshhika_1' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'summa_sborshhika_1' AND v3.meta_key = 'sborshchik-1-data' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_sborshhika_2' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'summa_sborshhika_2' AND v3.meta_key = 'sborshchik-2-data' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_sborshhika_3' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'summa_sborshhika_3' AND v3.meta_key = 'sborshchik-3-data' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_dostavki_v_czeh' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'czena_dostavki_v_czeh' AND v3.meta_key = 'data-zabora' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_dostavki_iz_czeha' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'czena_dostavki_iz_czeha' AND v3.meta_key = 'data-dostavki' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
OR (v1.meta_key = 'id_menedzhera' AND v1.meta_value = '%current_field|id_uchastnika%' AND v2.meta_key = 'summa_menedzhera' AND v3.meta_key = 'data-zakaza' AND v3.meta_value between '%current_field|data_1%' and '%current_field|data_2%')
)
and wp_posts.post_type='zakazy' and wp_posts.post_status='publish' ) t1


CROSS JOIN( SELECT COALESCE (sum(v2.meta_value),0) AS ....... t2

в %% указанны макросы для получения значения динамически.
  • Вопрос задан
  • 153 просмотра
Пригласить эксперта
Ответы на вопрос 1
3vi1_0n3
@3vi1_0n3
Выглядит достаточно плохо, но, мне кажется, я понимаю, какая у вас структура данных в базе плюс-минус.
Самый простой вариант оптимизации для начала:
SELECT t1.sum_za_zakazy AS sum_za_zakazy,  t2 .......

FROM ( SELECT COALESCE (sum(v2.meta_value),0) AS sum_za_zakazy
       FROM wp_posts
       JOIN wp_postmeta v1 ON (wp_posts.ID = v1.post_id)
       JOIN wp_postmeta v3 ON (wp_posts.ID = v3.post_id)
       JOIN wp_postmeta v2 ON (wp_posts.ID = v2.post_id)
WHERE wp_posts.post_type='zakazy'
AND wp_posts.post_status='publish'
AND v1.meta_value = '%current_field|id_uchastnika%'
AND v3.meta_value
    BETWEEN '%current_field|data_1%' AND '%current_field|data_2%'
AND (
   (v1.meta_key = 'id_shvei_1'           AND v2.meta_key = 'summa_shvei_1'           AND v3.meta_key = 'shveia-1-data')
OR (v1.meta_key = 'id_shvei_2'           AND v2.meta_key = 'summa_shvei_2'           AND v3.meta_key = 'shveia-2-data')
OR (v1.meta_key = 'id_shvei_3'           AND v2.meta_key = 'summa_shvei_3'           AND v3.meta_key = 'shveia-3-data')
OR (v1.meta_key = 'id_razborshhika_1'    AND v2.meta_key = 'summa_razborshhika_1'    AND v3.meta_key = 'razborshchik-1-data')
OR (v1.meta_key = 'id_razborshhika_2'    AND v2.meta_key = 'summa_razborshhika_2'    AND v3.meta_key = 'razborshchik-2-data')
OR (v1.meta_key = 'id_sborshhika_1'      AND v2.meta_key = 'summa_sborshhika_1'      AND v3.meta_key = 'sborshchik-1-data')
OR (v1.meta_key = 'id_sborshhika_2'      AND v2.meta_key = 'summa_sborshhika_2'      AND v3.meta_key = 'sborshchik-2-data')
OR (v1.meta_key = 'id_sborshhika_3'      AND v2.meta_key = 'summa_sborshhika_3'      AND v3.meta_key = 'sborshchik-3-data')
OR (v1.meta_key = 'id_dostavki_v_czeh'   AND v2.meta_key = 'czena_dostavki_v_czeh'   AND v3.meta_key = 'data-zabora')
OR (v1.meta_key = 'id_dostavki_iz_czeha' AND v2.meta_key = 'czena_dostavki_iz_czeha' AND v3.meta_key = 'data-dostavki')
OR (v1.meta_key = 'id_menedzhera'        AND v2.meta_key = 'summa_menedzhera'        AND v3.meta_key = 'data-zakaza')
)) t1

CROSS JOIN( SELECT COALESCE (sum(v2.meta_value),0) AS ....... t2


Так хотя бы более понятно.
Все общие условия выносите в начало. Всё, что используется всегда, для всех комбинаций ключей.
Я поменял порядок джоинов (v2 и v3), на случай, если планировщик не додумается, в каком порядке фильтровать, хотя я не уверен, что это будет проблемой, но планировщики не всегда работают умно, иногда надо подсказывать. По дефолту JOIN в MySQL, если правильно помню, INNER, поэтому в теории можно подрезать набор данных слева таким образом.
Вот после этого попробуйте, сравните время запроса и результат с тем, что до, и потом используйте EXPLAIN <ваш запрос>. Есть вероятность, что внутренний SELECT выполняется для каждой записи.
На поля wp_posts.post_type и wp_posts.post_status можно будет потом (при необходимости) сделать индексы, если их еще нет (можно комбинированный).
На wp_postmeta.meta_key исходя из полученной картины можно будет сделать индекс, если его еще нет, как и на wp_postmeta.meta_value, хотя я бы ожидал, честно говоря, что они уже есть.
Просто так индексы создавать не надо, только при необходимости.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы