优化查询以删除“使用where;使用临时;使用filesort”

时间:2011-01-24 14:17:51

标签: sql mysql optimization

我有一个简单的SQL查询,我正在尝试优化以删除“使用where;使用临时;使用filesort”。

这是表格:

CREATE TABLE `special_offers` (
  `so_id` int(11) NOT NULL auto_increment,
  `so_lid` int(11) NOT NULL,
  `so_product_id` int(11) NOT NULL,
  `so_bonus_product` int(11) NOT NULL,
  `so_reverse_relate` tinyint(1) NOT NULL default '0',
  `so_discount_amount` varchar(6) NOT NULL,
  `so_start` date NOT NULL default '0000-00-00',
  `so_expiry` date NOT NULL default '0000-00-00',
  `so_active` tinyint(1) NOT NULL,
  `so_archived` tinyint(4) NOT NULL default '0',
  `so_added` datetime NOT NULL,
  PRIMARY KEY  (`so_id`),
  KEY `so_archived` (`so_archived`),
  KEY `so_active` (`so_active`),
  KEY `so_start` (`so_start`),
  KEY `so_expiry` (`so_expiry`),
  KEY `so_product_id` (`so_product_id`),
  KEY `so_bonus_product` (`so_bonus_product`),
  KEY `so_lid` (`so_lid`)
) ENGINE=MyISAM AUTO_INCREMENT=65610 DEFAULT CHARSET=latin1

这是查询:

SELECT `so_id` , `so_lid` , `so_bonus_product` , `so_product_id`
FROM `special_offers`
WHERE `so_archived` = '0'
AND `so_active` = '1'
AND (
`so_start` <= CURDATE( )
OR `so_start` = '0000-00-00'
)
AND (
`so_expiry` >= CURDATE( )
OR `so_expiry` = '0000-00-00'
)
GROUP BY `so_lid`

解析:

mysql> EXPLAIN SELECT `so_id` , `so_lid` , `so_bonus_product` , `so_product_id` FROM `special_offers` WHERE `so_archived` = '0' AND `so_active` = '1' AND ( `so_start` <= CURDATE( ) OR `so_start` = '0000-00-00' ) AND ( `so_expiry` >= CURDATE( ) OR `so_expiry` = '0000-00-00' ) GROUP BY `so_lid`;
+----+-------------+-------------------+------+------------------------------------------+-------------+---------+-------+------+----------------------------------------------+
| id | select_type | table             | type | possible_keys                            | key         | key_len | ref   | rows | Extra                                        |
+----+-------------+-------------------+------+------------------------------------------+-------------+---------+-------+------+----------------------------------------------+
|  1 | SIMPLE      | special_offers    | ref  | so_archived,so_active,so_start,so_expiry | so_archived | 1       | const | 7684 | Using where; Using temporary; Using filesort |
+----+-------------+-------------------+------+------------------------------------------+-------------+---------+-------+------+----------------------------------------------+

4 个答案:

答案 0 :(得分:2)

(so_archived, so_active, so_lid, so_start, so_end)

上创建综合索引

答案 1 :(得分:0)

我有一句话,当使用日期函数时:

so_start` <= CURDATE( )

mysql不要使用此field so_start上的索引,

尝试在服务器端语言中输入实际日期

答案 2 :(得分:0)

我有一个综合索引(so_archived,so_active,so_lid)并添加一个关键字......

SELECT STRAIGHT_JOIN ...查询的其余部分

SELECT STRAIGHT_JOIN 
      `so_id` , `so_lid` , `so_bonus_product` , `so_product_id` 
  FROM 
      `special_offers` 
  WHERE 
          `so_archived` = '0' 
      AND `so_active` = '1' 
      AND ( `so_start` <= CURDATE( ) OR `so_start` = '0000-00-00' ) 
      AND ( `so_expiry` >= CURDATE( ) OR `so_expiry` = '0000-00-00' ) 
   GROUP BY 
      `so_lid` 

答案 3 :(得分:0)

我认为小组可能会给你带来麻烦。

SELECT  `so_id` , `so_lid` , `so_bonus_product` , `so_product_id` ... GROUP BY `so_lid`

so_lid进行分组时,so_idso_bonus_productso_product_id的值对于给定的so_lid都是相同的。您可能会发现意外结果。这也可能导致优化问题。

请参阅此文章。 http://dev.mysql.com/tech-resources/articles/debunking-group-by-myths.html