@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

в %% указанны макросы для получения значения динамически.
  • Вопрос задан
  • 146 просмотров
Пригласить эксперта
Ответы на вопрос 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, хотя я бы ожидал, честно говоря, что они уже есть.
Просто так индексы создавать не надо, только при необходимости.
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы