Оптимизировать левое соединение с несколькими объединениями по ИЛИ? - PullRequest
0 голосов
/ 30 января 2019

Это мой запрос (отредактированный)

SELECT
  en.name AS name,
  en.entity_id,
  COUNT(o.order_id) AS orders_qty,
  ROUND(SUM(o.total)) AS orders_sum,
  ROUND((SUM(o.total) / COUNT(o.order_id))) AS average_purchase,
  MIN(o.date_added) AS first_purchase,
  MAX(o.date_added) AS last_purchase,
  (SELECT COUNT(*) FROM oc_order WHERE order_status_id <> 0 AND customer_id = c.customer_id AND date_added <= NOW() - INTERVAL 3 MONTH) as periodicity
FROM oc_xile_entity en
  LEFT JOIN oc_xile_customer_to_entity c2en ON (c2en.entity_id = en.entity_id)
  LEFT JOIN oc_customer c ON (c2en.customer_id = c.customer_id)
LEFT JOIN oc_order o FORCE INDEX FOR JOIN (`unreg_customer_id`) ON ((o.customer_id = c2en.customer_id OR o.unreg_customer_id = c2en.customer_id) AND order_status_id <> 0)
  WHERE en.entity_id IS NOT NULL
GROUP BY en.entity_id
ORDER BY name ASC
LIMIT 0,700

... и соответствующие части таблиц ...

CREATE TABLE oc_order 
( order_id int(11) NOT NULL PRIMARY KEY 
, customer_id int(11) NOT NULL DEFAULT '0'
, unreg_customer_id (unreg_customer_id)
, unreg_customer_id int(11) NOT NULL
, order_status_id int(11) NOT NULL DEFAULT '0'
, INDEX (customer_id)
);

CREATE TABLE oc_customer 
(customer_id int(11) NOT NULL PRIMARY KEY);

CREATE TABLE oc_xile_customer_to_entity 
(entity_id int(11) NOT NULL
,customer_id int(11) NOT NULL
,PRIMARY KEY (entity_id,customer_id)
,INDEX entity_id
);

Когда я выполняю запрос, он занимает более 15 секундв порядке таблицы 35506 строк

Самый тяжелый запрос - это

LEFT JOIN oc_order o ON ((o.customer_id = c2en.customer_id OR o.unreg_customer_id = c2en.customer_id) AND order_status_id  0)

Лучший способ оптимизировать его, добавив FORCE INDEX FOR JOIN (unreg_customer_id) вот так LEFT JOIN oc_order o FORCE INDEX FOR JOIN (unreg_customer_id) ON ((o.customer_id = c2en.customer_id OR o.unreg_customer_id = c2en.customer_id) AND order_status_id <> 0), его скорость увеличения и время запроса стали 3secs,Но я думаю, что это может оптимизировать намного лучше.Кто-нибудь может мне помочь?Объяснение запроса explain

1 Ответ

0 голосов
/ 31 января 2019

Duh?Запрос ничего не делает с LEFT JOINs.Однако Оптимизатор, вероятно, слишком глуп, чтобы отбросить их и получить эквивалентный запрос:

SELECT  en.name AS name , en.entity_id
    FROM  oc_xile_entity en
    WHERE  en.entity_id IS NOT NULL
    GROUP BY  en.entity_id
    ORDER BY  name ASC
    LIMIT  0 , 700

Тогда, вероятно, будет «неправильным», если вы выбираете name, но не группируете по нему.Если есть несколько names, связанных с одним entity_id, то , который name должен отображаться?

Пожалуйста, опишите, чего вы пытаетесь достичь, плюс укажите SHOW CREATE TABLE oc_xile_entity.

...