我有一个示例查询,例如:
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;
Run Code Online (Sandbox Code Playgroud)
只是想知道下面两个索引,哪个最好在餐厅桌上?
id,state,status,name
state,status,name
Run Code Online (Sandbox Code Playgroud)
只是不确定是否应该包含连接中使用的列?
有趣的是,我已经创建了两种类型的测试,并且两次MySQL选择主要索引,这只是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'
Run Code Online (Sandbox Code Playgroud)
目前没有多少行,所以也许这就是它选择PRIMARY的原因!?
为了获得最佳性能,您至少需要 2 个索引:
最重要的索引是外键上的索引:
CREATE INDEX specials_rest_fk ON specials(restaurantid);
Run Code Online (Sandbox Code Playgroud)
如果没有这个,您的查询将表现不佳,因为rest匹配WHERE条件的每一行都需要对specials.
rest要定义的下一个索引将是帮助查找给定条件的最少行的索引。仅使用了一个索引,因此您希望使该索引查找尽可能少的行rest。
我的猜测、状态和状态:
CREATE INDEX rest_index_1 on rest(state, status);
Run Code Online (Sandbox Code Playgroud)
您的 (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;
Run Code Online (Sandbox Code Playgroud)
请注意该条款中现在特价商品的条件ON。