我有一个运行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|
+--+------------------+---------+----+------------------------+----------+-------+-------+------+-----------+
答案 0 :(得分: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
结构数为0的产品需要IS NULL
部分,因为它们在连接中不匹配。对于查询处理器来说,查询应该更容易使用适当的索引。如果它仍然不使用它们,请检查您是否在正确的列上。