0

我有一个运行 114 秒的 SQL 查询。该表包含 224000 行。

为什么不使用“产品”表的键?

有人对如何优化此查询有一些想法吗?

EXPLAIN SELECT SUM( quantity * ( 
SELECT IF( netoweight =  '', weight, netoweight ) AS weight
FROM products
WHERE product_nr = it.item ) /1000 ) 
FROM  `inventory_transactions` it
WHERE it.type =  'Production'
AND it.item >  '200000'
AND it.item <  '400000'
AND it.date LIKE  '2013-01%'
AND (
(

SELECT COUNT( id ) 
FROM structure
WHERE final_item = it.item
AND level >  '1'
) <1
)

+--+------------------+---------+----+------------------------+----------+-------+-------+------+-----------+
|id|select_type       |table    |type|possible_keys           |key       |key_len|ref    |rows  |Extra      |
+--+------------------+---------+----+------------------------+----------+-------+-------+------+-----------+
|1 |PRIMARY           |it       |ref |item,type,date          |type      |50     |const  |111604|Using where|
+--+------------------+---------+----+------------------------+----------+-------+-------+------+-----------+
|3 |DEPENDENT SUBQUERY|structure|ref |final_item,level,level_2|final_item|4      |it.item|8     |Using where|
+--+------------------+---------+----+------------------------+----------+-------+-------+------+-----------+
|2 |DEPENDENT SUBQUERY|products |ALL |product_nr              |NULL      |NULL   |NULL   |3831  |Using where|
+--+------------------+---------+----+------------------------+----------+-------+-------+------+-----------+
4

1 回答 1

1

MySQL 在优化这样的子查询方面真的很糟糕,所以你必须帮助它,如果可能的话,使用连接重写它。对于第一个子查询,这应该很容易:

SELECT SUM( quantity * weight /1000 ) 
FROM  `inventory_transactions` it
JOIN (SELECT product_nr, IF( netoweight =  '', weight, netoweight ) AS weight
     FROM products) AS products
ON product.product_nr = it.item
WHERE it.type =  'Production'
AND it.item >  '200000'
AND it.item <  '400000'
AND it.date LIKE  '2013-01%'
AND (
(

SELECT COUNT( id ) 
FROM structure
WHERE final_item = it.item
AND level >  '1'
) <1
)

但是,这可能还不能解决不使用产品表上的键的问题,因为第二个查询更复杂。但是,它应该可以使用 group by 重写:

SELECT SUM( quantity * weight /1000 ) 
FROM  `inventory_transactions` it
JOIN (SELECT product_nr, IF( netoweight =  '', weight, netoweight ) AS weight
     FROM products) AS products,
ON product.product_nr = it.item
LEFT OUTER JOIN (SELECT final_item, COUNT( id ) AS count
    FROM structure
    WHERE level > '1'
    GROUP BY final_item) AS struct_count
ON it.item = struct_count.final_item
WHERE it.type =  'Production'
AND it.item >  '200000'
AND it.item <  '400000'
AND it.date LIKE  '2013-01%'
AND struct_count.count IS NULL

IS NULL结构计数为 0 的产品需要该部件,因为它们在连接中不匹配。这个查询应该更容易让查询处理器使用适当的索引。如果它仍然不会使用它们,请检查它们是否位于正确的列中。

于 2013-09-06T06:14:16.097 回答