5

I have an example query such as:

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;

Just wondering of the below two indexes, which would be best on the restaurant table?

id,state,status,name
state,status,name

Just not sure if column used in the join should be included?

Funny enough though, I have created both types for testing and both times MySQL chooses the primary index, which is just id. Why is that?

Explain Output:

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'

Not many rows at the moment so perhaps that's why it's choosing PRIMARY!?

4

1 回答 1

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 页读取的条目更少。

但是您也可以通过更好地编写查询来获得性能;如果将 specials 上的条件移动到连接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子句中。

于 2012-12-16T17:26:11.650 回答