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

Bre*_*ett 5 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;
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的原因!?

Boh*_*ian 2

为了获得最佳性能,您至少需要 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