加快mysql查询

时间:2018-10-23 12:01:12

标签: mysql performance

我有一个mysql查询来联接四个表,我认为最好是联接表,但是现在mysql数据越来越大,查询似乎导致应用程序停止执行。

 SELECT 
                        `purchase_order`.`id`, 
                        `purchase_order`.`po_date` AS po_date, 
                        `purchase_order`.`po_number`, 
                        `purchase_order`.`customer_id` AS customer_id , 
                        `customer`.`name` AS customer_name, 
                        `purchase_order`.`status` AS po_status, 
                        `purchase_order_items`.`product_id`, 
                        `purchase_order_items`.`po_item_name`, 
                        `product`.`weight` as product_weight,
                        `product`.`pending` as product_pending,
                        `product`.`company_owner` as company_owner,
                        `purchase_order_items`.`uom`, 
                        `purchase_order_items`.`po_item_type`, 
                        `purchase_order_items`.`order_sequence`, 
                        `purchase_order_items`.`pending_balance`, 
                        `purchase_order_items`.`quantity`, 
                        `purchase_order_items`.`notes`, 
                        `purchase_order_items`.`status` AS po_item_status,
                        `purchase_order_items`.`id` AS po_item_id
                      FROM `purchase_order` 
                      INNER JOIN customer ON `customer`.`id` = `purchase_order`.`customer_id`  
                      INNER JOIN purchase_order_items ON `purchase_order_items`.`po_id` = `purchase_order`.`id` 
                      INNER JOIN product ON `purchase_order_items`.`product_id` = `product`.`id`
GROUP BY id ORDER BY `purchase_order`.`po_date` DESC LIMIT 0, 20

enter image description here

我的问题确实是需要很多时间才能完成的查询。有没有一种方法可以加快此查询或更改此查询以更快地检索数据?

此处是注释中要求的EXPLAIN EXTENED。 enter image description here 在此先感谢,我真的希望这是我提出要求的正确渠道。如果没有,请告诉我。

4 个答案:

答案 0 :(得分:1)

您需要确保purchase_order.po_date和所有id列都已建立索引。您可以通过以下查询进行检查。

SHOW INDEX FROM yourtable;

答案 1 :(得分:1)

这会给您正确的ID列表吗?

SELECT id
    FROM purchase_order
    ORDER BY`po_date` DESC
    LIMIT 0, 20

如果是这样,则在启动进入JOIN之前先以 start 开始。您也可以(我认为)摆脱引起行“爆炸爆炸”的GROUP BY

SELECT ...
    FROM ( SELECT id ... (as above) ...) AS ids
    JOIN purchase_order po  ON po.id = ids.id
    JOIN ... (the other tables)
    GROUP BY ...   -- (this may be problematic, especially with the LIMIT)
    ORDER BY po.po_date DESC   -- yes, this needs repeating
    -- no LIMIT

类似这样的东西

SELECT 
                        `purchase_order`.`id`, 
                        `purchase_order`.`po_date` AS po_date, 
                        `purchase_order`.`po_number`, 
                        `purchase_order`.`customer_id` AS customer_id , 
                        `customer`.`name` AS customer_name, 
                        `purchase_order`.`status` AS po_status, 
                        `purchase_order_items`.`product_id`, 
                        `purchase_order_items`.`po_item_name`, 
                        `product`.`weight` as product_weight,
                        `product`.`pending` as product_pending,
                        `product`.`company_owner` as company_owner,
                        `purchase_order_items`.`uom`, 
                        `purchase_order_items`.`po_item_type`, 
                        `purchase_order_items`.`order_sequence`, 
                        `purchase_order_items`.`pending_balance`, 
                        `purchase_order_items`.`quantity`, 
                        `purchase_order_items`.`notes`, 
                        `purchase_order_items`.`status` AS po_item_status,
                        `purchase_order_items`.`id` AS po_item_id
    FROM (SELECT id, po_date, po_number, customer_id, status
            FROM purchase_order
            ORDER BY `po_date` DESC
            LIMIT 0, 5) as purchase_order 
    INNER JOIN customer ON `customer`.`id` = `purchase_order`.`customer_id`  
    INNER JOIN purchase_order_items
         ON `purchase_order_items`.`po_id` = `purchase_order`.`id` 
    INNER JOIN product ON `purchase_order_items`.`product_id` = `product`.`id`
    GROUP BY purchase_order.id DESC
    LIMIT 0, 5

答案 2 :(得分:0)

由于您提到数据越来越大。我建议进行分片,然后可以并行化多个查询。请参考以下文章

Parallel Query for MySQL with Shard-Query

答案 3 :(得分:0)

首先,我整理了一些可读性。您不需要在每个table.column引用周围使用tick标记。此外,对于速记而言,使用别名效果很好。例如:“ po”代替“ purchase_order”,“ poi”代替“ purchase_order_items”。我唯一要使用刻度线的地方是保留字,这可能会引起问题。

第二,您的查询中没有任何汇总(总和,最小值,最大值,计数,平均值等),因此您应该能够删除GROUP BY子句。

对于索引,我必须假设您的引用表上的相应“ id”键列上都有索引。

对于您的采购订单表,如果您已经有了使用它的索引,我将在第一个索引字段位置基于“ po_date”在该索引上进行索引。由于您的Order by处于该状态,因此让引擎首先直接跳转到那些有日期的记录,然后您就可以解决降序的问题。

SELECT 
      po.id, 
      po.po_date, 
      po.po_number, 
      po.customer_id, 
      c.`name` AS customer_name, 
      po.`status` AS po_status, 
      poi.product_id, 
      poi.po_item_name, 
      p.weight as product_weight,
      p.pending as product_pending,
      p.company_owner,
      poi.uom, 
      poi.po_item_type, 
      poi.order_sequence, 
      poi.pending_balance, 
      poi.quantity, 
      poi.notes, 
      poi.`status` AS po_item_status,
      poi.id AS po_item_id
   FROM 
      purchase_order po
         INNER JOIN customer c
            ON po.customer_id = c.id
         INNER JOIN purchase_order_items poi 
            ON po.id = poi.po_id
            INNER JOIN product p 
               ON poi.product_id = p.id
   ORDER BY 
      po.po_date DESC 
   LIMIT 
      0, 20