【问题标题】:Speed up slow 3 table MYSQL query加速慢3表MYSQL查询
【发布时间】:2015-09-15 19:57:13
【问题描述】:

我正在查询电子商务网站中的 3 个表。

订单表:

id
order_number
name
etc...

order_lines 表:

id
order_number
sku
quantity
etc.

产品表

id
sku
title
ship_by (INT)
etc.

order_numberorders 表链接到 order_lines 表。 SKUorder_lines 表链接到 products 表。

请注意 products 表中的 ship_by 列,这表示将由哪个供应商发货。查询需要为特定供应商拉订单。订单可能包含由不同供应商销售的商品。

这是我拼凑起来的查询:

SELECT 
    orders.`order_number`               as `orderId`,
    orders.`shipping`                   as `fPostageCost`,
     FROM_UNIXTIME(orders.`time`)       as `dReceievedDate`,
    (
    CASE orders.`dob`
    WHEN 'COURIER 3 DAY' THEN 'UK_SellersStandardRate'
    WHEN 'COURIER 24 HOUR' THEN 'UK_OtherCourier24'
    ELSE orders.`dob`
    END
    )                       
    ...(plus a number more)

 FROM orders
 INNER JOIN order_lines
 ON   orders.order_number = order_lines.order_number
 WHERE 
       ( 
         (SELECT COUNT(order_lines.sku) 
          FROM order_lines, products 
          WHERE order_lines.sku = products.sku 
          AND products.ship_by = 1 
          AND order_lines.order_number = orders.order_number) > 0 
       )
       AND ( orders.`printed` = 'N' OR orders.`printed` IS NULL )
       AND orders.status = 'Awaiting Despatch'
       AND ( orders.payment_status = 'Success' OR orders.payment_status = 'Paypal Paid' OR orders.payment_status = 'Manual Payment' )
  GROUP BY orders.`order_number`
  ORDER BY orders.order_number ASC

执行查询大约需要 7 秒。

如果我从第二个 SELECT 查询中删除 'AND order_lines.order_number = orders.order_number' 行,它几乎会立即执行,但如果没有这一行,它就不能按我的需要工作。

除了将“ship_by”列添加到 order_lines 表中(我不想这样做,因为我必须更改很多 php 代码),有没有办法修改这个查询来加快它的速度?

查询是从 PHP 外部运行的,所以它必须是纯 mysql 查询。

这里是查询的解释:

id  select_type         table        type     possible_keys     key         key_len     ref                                     rows    Extra
1   PRIMARY             order_lines  ALL      NULL              NULL        NULL        NULL                                    9627    Using temporary; Using filesort
1   PRIMARY             orders       eq_ref   order_idx         order_idx   17          .order_lines.order_number   1       Using where
2   DEPENDENT SUBQUERY  order_lines  ALL      NULL              NULL        NULL        NULL                                    9627    Using where
2   DEPENDENT SUBQUERY  products     ref      sku_2,sku,sku_3   sku_2       63          order_lines.prod_code   11      Using where

谢谢

【问题讨论】:

    标签: php mysql database


    【解决方案1】:

    您的order_lines 表至少需要order_number 上的索引。我们需要查看架构以最好地选择一个。也许综合指数会在其他领域加速。

    但在选择索引更改时,必须仔细权衡系统中的其他查询以及对插入和更新速度的影响。

    目标不应该是让 10% 的应用程序快速,而牺牲 90%。

    要显示非常有用的信息,请发布show create table tableName 以获取相关表名。 (而不是徒手描述它,就像我的桌子有这个和那个)。我们需要查看订单、order_lines、产品的架构。

    Create Index上的手册页

    【讨论】:

      【解决方案2】:

      知道表格在您的内联视图中有多大,但如果它很大,那么 使用联合可能会有所帮助,而不必为每条记录查询视图。

      类似的东西。

          SELECT L1*
      FROM 
      (SELECT 
          orders.`order_number`               as `orderId`,
          0                                   AS  SKU_CNT,
          orders.`shipping`                   as `fPostageCost`,
           FROM_UNIXTIME(orders.`time`)       as `dReceievedDate`,
          (
          CASE orders.`dob`
          WHEN 'COURIER 3 DAY' THEN 'UK_SellersStandardRate'
          WHEN 'COURIER 24 HOUR' THEN 'UK_OtherCourier24'
          ELSE orders.`dob`
          END
          )                       
          ...(plus a number more)
      
       FROM orders
       INNER JOIN order_lines
       ON   orders.order_number = order_lines.order_number
       WHERE  ( orders.`printed` = 'N' OR orders.`printed` IS NULL )
             AND orders.status = 'Awaiting Despatch'
             AND ( orders.payment_status = 'Success' OR orders.payment_status = 'Paypal Paid' OR orders.payment_status = 'Manual Payment' )
      
      
       UNION ALL
          Select
          0                       AS  ORDERID,
          COUNT(OL.SKU)           AS  SKU_CNT,
          0                       as `fPostageCost`,
          NULL                    as `dReceievedDate`,
          ...
          FROM ORDER_LINES OL,
               PRODUCTS PR
          WHERE order_lines.sku = products.sku 
                AND products.ship_by = 1 
                AND order_lines.order_number = orders.order_number     
          GROUP BY ORDERID, ORDER_LINES_CNT, fPostageCost`, dReceievedDate`,
      )L1
      WHERE L1.SKU_CNT > 0
      GROUP BY L1.`order_number`
      ORDER BY L1.order_number ASC
      

      【讨论】:

        【解决方案3】:

        您可以将子查询替换为exists

        WHERE EXISTS (SELECT 1
                      FROM order_lines ol2 JOIN
                           products p2
                           ON ol2.sku = p.sku AND
                              p2.ship_by = 1 
                              ol.order_number = o.order_number
                     ) AND
                . . .
        

        但是,您的查询 sn-p 没有在外部查询中使用 order_lines。我怀疑您可以通过聚合摆脱它:

        FROM orders o
        WHERE EXISTS (SELECT 1
                      FROM order_lines ol2 JOIN
                           products p2
                           ON ol2.sku = p2.sku AND
                              p2.ship_by = 1 
                              ol.order_number = o.order_number
                     ) AND
                . . .
        

        这至少会返回所有订单信息——缺少聚合可能会简化查询的其他部分。如果某些版本的查询运行得很快,那么索引的设置可能是合理的。

        【讨论】:

        • 感谢@drew & snowsprinkle 的回答。我首先尝试了 Gordon 的建议,并基于此将 sql 更改为现在阅读:SELECT o.order_number ...etc FROM orders o, order_lines ol, products p WHERE ol.sku = p.sku AND p.ship_by = 1 AND ol.order_number = o.order_number AND ( o.printed` = 'N' OR o.printed IS NULL ) AND o.status = 'Awaiting Despatch' AND (o.payment_status = 'Success' OR o.payment_status = 'Paypal Paid' OR o.payment_status = 'Manual Payment' ) GROUP BY o.order_number ORDER BY o.order_number ASC`
        • ...现在查询在 0.05 秒内完成。快 140 倍。杰出的!我需要提高我的mysql知识。我想是时候寻找一本新书了。再次感谢。
        猜你喜欢
        • 2016-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-22
        • 2014-10-20
        • 2011-07-30
        • 1970-01-01
        相关资源
        最近更新 更多