我有一个示例查询,例如:
SELECT
rest.name, rest.shortname
FROM
restaurant AS rest
INNER JOIN specials ON rest.id=specials.restaurantid
WHERE
specials.dateend >= CURDATE()
AND
rest.state='VIC'
AND
rest.status = 1
AND
specials.status = 1
ORDER BY
rest.name ASC;
只是想知道以下两个指数,哪个最好在餐厅桌上?
id,state,status,name
state,status,name
不确定是否应包含联接中使用的列?
有趣的是,我已经为测试创建了两种类型,并且两次MySQL都选择 primary 索引,这只是id
。那是为什么?
解释输出:
1,'SIMPLE','specials','index','NewIndex1\,NewIndex2\,NewIndex3\,NewIndex4','NewIndex4','11',\N,82,'Using where; Using index; Using temporary; Using filesort',
1,'SIMPLE','rest','eq_ref','PRIMARY\,search\,status\,state\,NewIndex1\,NewIndex2\,id-suburb\,NewIndex3\,id-status-name','PRIMARY','4','db_name.specials.restaurantid',1,'Using where'
目前没有多少行,所以也许这就是为什么它选择PRIMARY!?
答案 0 :(得分:2)
为获得最佳性能,您至少需要2个索引:
最重要的索引是外键上的索引:
CREATE INDEX specials_rest_fk ON specials(restaurantid);
如果不这样做,您的查询效果会很差,因为rest
中符合WHERE
条件的每一行都需要specials
的完整表扫描。
要定义的下一个索引将是根据您的条件帮助查找rest
的最少行的索引。只使用了一个索引,因此您希望尽可能少地从rest
中查找该索引。
我的猜测,状态和状态:
CREATE INDEX rest_index_1 on rest(state, status);
你的(id,...)的索引建议是没有意义的,因为id是唯一的 - 添加更多列将无济于事,并且实际上如果使用它会使性能恶化,因为索引条目会更大而你每次读取I / O页面的条目越少。
但是你也可以通过更好地编写查询来获得性能;如果将特殊条件移动到连接ON
条件,则会获得显着的性能,因为连接条件是在进行连接时计算的,但是在所有连接的行上评估条件,这意味着临时结果集由WHERE
子句过滤的更大,因此更慢。
将您的查询更改为:
SELECT rest.name, rest.shortname
FROM restaurant AS rest
INNER JOIN specials
ON rest.id=specials.restaurantid
AND specials.dateend >= CURDATE()
AND specials.status = 1
WHERE rest.state='VIC'
AND rest.status = 1
ORDER BY rest.name;
请注意特殊条件现在如何在ON
子句中。