Чрезвычайно медленный SQL-запрос выбора - PullRequest
0 голосов
/ 18 января 2012

Следующий запрос:

SELECT 
  `so`.*,
  IF(
    ISNULL(`ips`.`border`),
    `io`.`cdborder`,
    `ips`.`border`
  ) AS order_status,
  IF(
    ISNULL(`ips`.`status`),
    `io`.`cdstatus`,
    `ips`.`status`
  ) AS order_state,
  `io`.*,
  IF(
    ISNULL(`ips`.`sale`),
    `iol`.`regelstatus`,
    `ips`.`sale`
  ) AS order_line_status 
FROM
  `sales_order` AS `so` 
  INNER JOIN `sales_flat_order_item` AS `soi` 
    ON soi.order_id = so.entity_id 
  LEFT JOIN `import`.`import_orders` AS `io` 
    ON so.atorder_id = io.cdorder 
    AND so.cdadmin = io.cdadmin 
    AND (error_msg IS NULL 
      OR error_msg = "") 
  LEFT JOIN `import`.`import_orderlines` AS `iol` 
    ON iol.cdorder = so.atorder_id 
    AND iol.cdadmin = so.cdadmin 
  LEFT JOIN `import`.`import_purchase_sales` AS `ips` 
    ON so.atorder_id = ips.order 
WHERE (soi.sku IS NULL) 
  OR (
    soi.sku = iol.cdproduct 
    AND (
      soi.atorder_line = iol.nrordrgl
    ) 
    AND (
      iol.atg != soi.qty_shipped 
      OR iol.at != soi.qty_invoiced 
      OR iol.atb != soi.qty_ordered
    )
  ) 
GROUP BY `so`.`atorder_id`,
  `so`.`cdadmin` 
ORDER BY `io`.`modification_date_order` ASC 
LIMIT 200 

Требуется 4 минуты для выполнения!Как это может быть?Объяснение показывает следующее:

id     select_type     table     type         possible_keys         key         key_len     ref                                         rows     Extra
1      SIMPLE          so        index        PRIMARY               order_id    32          NULL                                        127828   Using temporary; Using filesort
1      SIMPLE          io        eq_ref       PRIMARY,error_msg     PRIMARY     261         livetest3.so.order_id,livetest3.so.cdadmin  1     
1      SIMPLE          soi       ref          IDX_ORDER             IDX_ORDER   4           livetest3.so.entity_id                      2             
1      SIMPLE          iol       ref          cdorder               cdorder     258         livetest3.so.order_id                       6        Using where
1      SIMPLE          ips       ref          sale_order            sale_order  32          livetest3.so.order_id                       3

Я пробовал несколько инструментов профилировщика запросов, но ни один не показывает мне подробную информацию о том, какая часть запроса является настолько медленной ...

Только таблица 'так'содержит 130 тыс. строк ... Даже с кучей левых соединений не должно быть так медленно ... Есть идеи?

Ответы [ 4 ]

1 голос
/ 18 января 2012

Не зная точно, что вы ХОТИТЕ из данных, в вашем запросе есть экземпляр «soi.sku IS NULL», который подразумевает ЛЕВОЕ СОЕДИНЕНИЕ с этим псевдонимом.У вас было нормальное соединение, указывающее, что вы ВСЕГДА хотели, чтобы запись соответствовала «soi». Вы хотели вместо этого передать это в LEFT JOIN?Если вы ВСЕГДА хотите использовать «soi», то я бы удалил часть запроса «soi.sku IS NULL ИЛИ» в этом случае.

Кроме этого, сам запрос выглядит нормально, однако я бы позаботилсяявно имеют следующие индексы.

Table                         Index
Sales_Order                   (atorder_id, ccadmin)
import.import_orderlines      (cdorder, cdadmin)
import.import_orders          (cdorder, cdadmin)
import.import_purchase_sales  (order)

Затем измените

SELECT ... 

на

SELECT STRAIGHT_JOIN ...
1 голос
/ 18 января 2012

Кажется, что первичный ключ - order_id, но ваш запрос вообще не может его использовать. Если вы создаете индекс для sku, ваш запрос должен выполняться быстрее.

Обратите внимание, что есть место для дальнейших улучшений, но я бы начал с создания индекса на sku и повторно запустил запрос, чтобы посмотреть, как он работает сейчас.

1 голос
/ 18 января 2012

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

1 голос
/ 18 января 2012

ОБЪЯСНЕНИЕ дало вам всю необходимую информацию.Using temporary; Using filesort - это медленная часть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...