为什么不使用索引查询以及如何优化它?

时间:2013-09-06 06:01:15

标签: mysql sql optimization indexing key

我有一个运行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|
+--+------------------+---------+----+------------------------+----------+-------+-------+------+-----------+

1 个答案:

答案 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部分,因为它们在连接中不匹配。对于查询处理器来说,查询应该更容易使用适当的索引。如果它仍然不使用它们,请检查您是否在正确的列上。