在HAVING子句中索引列 - MySQL

时间:2013-02-06 10:02:00

标签: mysql select indexing having

我有一张超过12列的表格。这是用于检索最新7条记录的mysql查询

SELECT * FROM data WHERE user_id IN(12,10,7,1) HAVING continent IN('Europe','America','Australia') AND NOT MATCH(weather) AGAINST('+"[blues]"' IN BOOLEAN MODE) || continent = 'Asia' AND MATCH(weather) AGAINST('+"[purples]"' IN BOOLEAN MODE) ORDER BY tb_id DESC LIMIT 7

总行数超过5 millionuser_id是一个索引列,tb_idPRIMARY KEY。当我使用EXPLAIN前面的SELECT时。 MySQL告诉它将从总计500万条中读取超过40万条记录。

那么我应该对大陆专栏进行索引,否则在这种情况下无效?

这是EXPLAIN结果

id = 1; select_type = SIMPLE; table = data; possible_keys = user_id; key = user_id; ref = NULL; rows = 582; Extra = Using where, Using filesort

1 个答案:

答案 0 :(得分:1)

首先,您的查询可能是错误的。当您在{或1}}中使用OR与where或者where子句中的AND混合时,您应该使用parantheses。

其次,在您的情况下使用HAVING没有意义,优化器很可能将其转换为WHERE子句。

两者之间的区别在于,在确定要选择的行时应用WHEREHAVING应用于结果集。所以,如果优化器不能很好地完成,你首先会得到(差不多)所有行,然后对它们进行过滤。当你把它全部放在WHERE子句中时,你只得到相关的行。 HAVING(几乎)仅在您使用GROUP BY时才有意义。

因此,您最好以这种方式编写查询:

SELECT * FROM data 
WHERE user_id IN(12,10,7,1) AND
(
(
continent IN('Europe','America','Australia') 
AND NOT MATCH(weather) AGAINST('+"[blues]"' IN BOOLEAN MODE) 
)
OR 
(
continent = 'Asia' 
AND MATCH(weather) AGAINST('+"[purples]"' IN BOOLEAN MODE) 
)
)
ORDER BY tb_id DESC LIMIT 7

要回答有关索引的问题,请发布解释结果和表data的创建语句。