我有一个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
我的问题确实是需要很多时间才能完成的查询。有没有一种方法可以加快此查询或更改此查询以更快地检索数据?
此处是注释中要求的EXPLAIN EXTENED。 在此先感谢,我真的希望这是我提出要求的正确渠道。如果没有,请告诉我。
答案 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)
由于您提到数据越来越大。我建议进行分片,然后可以并行化多个查询。请参考以下文章
答案 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