什么类型的索引是此查询的理想选择?

时间:2012-12-16 14:37:13

标签: mysql indexing

我有一个示例查询,例如:

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!?

1 个答案:

答案 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子句中。