了解mysql解释

Pau*_*jan 19 mysql database optimization database-design

所以,我从来没有理解MySQL的解释.我理解你应该在possible_keys列中至少有一个条目使用索引的粗略概念,并且简单的查询更好.但是ref和eq_ref有什么区别?优化查询的最佳方法是什么?

例如,这是我最新的查询,我试图弄清楚为什么它需要永远(从django模型生成):

+----+-------------+---------------------+--------+-----------------------------------------------------------+---------------------------------+---------+--------------------------------------+------+---------------------------------+
| id | select_type | table               | type   | possible_keys                                             | key                             | key_len | ref                                  | rows | Extra                           |
+----+-------------+---------------------+--------+-----------------------------------------------------------+---------------------------------+---------+--------------------------------------+------+---------------------------------+
|  1 | SIMPLE      | T6                  | ref    | yourock_achiever_achievement_id,yourock_achiever_alias_id | yourock_achiever_alias_id       | 4       | const                                |  244 | Using temporary; Using filesort |
|  1 | SIMPLE      | T5                  | eq_ref | PRIMARY                                                   | PRIMARY                         | 4       | paul.T6.achievement_id               |    1 | Using index                     |
|  1 | SIMPLE      | T4                  | ref    | yourock_achiever_achievement_id,yourock_achiever_alias_id | yourock_achiever_achievement_id | 4       | paul.T6.achievement_id               |  298 |                                 |
|  1 | SIMPLE      | yourock_alias       | eq_ref | PRIMARY                                                   | PRIMARY                         | 4       | paul.T4.alias_id                     |    1 | Using index                     |
|  1 | SIMPLE      | yourock_achiever    | ref    | yourock_achiever_achievement_id,yourock_achiever_alias_id | yourock_achiever_alias_id       | 4       | paul.T4.alias_id                     |  152 |                                 |
|  1 | SIMPLE      | yourock_achievement | eq_ref | PRIMARY                                                   | PRIMARY                         | 4       | paul.yourock_achiever.achievement_id |    1 |                                 |
+----+-------------+---------------------+--------+-----------------------------------------------------------+---------------------------------+---------+--------------------------------------+------+---------------------------------+
6 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

我本来希望学习足够的mysql解释说不需要查询.唉,似乎你无法从explain语句中获得足够的信息,而你需要原始的SQL.查询:

SELECT  `yourock_achievement`.`id`,
        `yourock_achievement`.`modified`,
        `yourock_achievement`.`created`,
        `yourock_achievement`.`string_id`,
        `yourock_achievement`.`owner_id`,
        `yourock_achievement`.`name`,
        `yourock_achievement`.`description`,
        `yourock_achievement`.`owner_points`,
        `yourock_achievement`.`url`,
        `yourock_achievement`.`remote_image`,
        `yourock_achievement`.`image`,
        `yourock_achievement`.`parent_achievement_id`,
        `yourock_achievement`.`slug`,
        `yourock_achievement`.`true_points`
FROM    `yourock_achievement`
INNER JOIN
        `yourock_achiever`
ON       `yourock_achievement`.`id` = `yourock_achiever`.`achievement_id`
INNER JOIN
        `yourock_alias`
ON      `yourock_achiever`.`alias_id` = `yourock_alias`.`id`
INNER JOIN
        `yourock_achiever` T4
ON      `yourock_alias`.`id` = T4.`alias_id`
INNER JOIN
        `yourock_achievement` T5
ON      T4.`achievement_id` = T5.`id`
INNER JOIN
        `yourock_achiever` T6
ON      T5.`id` = T6.`achievement_id`
WHERE
        T6.`alias_id` = 6
ORDER BY
        `yourock_achievement`.`modified` DESC
Run Code Online (Sandbox Code Playgroud)

hob*_*ave 18

保罗:

eq_ref

对于前面表格中的每个行组合,从该表中读取一行.除了system和const类型之外,这是最好的连接类型.当连接使用索引的所有部分并且索引是PRIMARY KEY或UNIQUE索引时使用它.

eq_ref可用于使用=运算符进行比较的索引列.比较值可以是常量,也可以是使用在此表之前读取的表中的列的表达式.在以下示例中,MySQL可以使用eq_ref连接来处理ref_table:

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
Run Code Online (Sandbox Code Playgroud)

REF

对于上一个表中的每个行组合,将从此表中读取所有具有匹配索引值的行.如果连接仅使用键的最左前缀或者键不是PRIMARY KEY或UNIQUE索引(换句话说,如果连接不能基于键值选择单行),则使用ref.如果使用的密钥只匹配几行,这是一个很好的连接类型.

ref可用于使用=或<=>运算符进行比较的索引列.在以下示例中,MySQL可以使用ref join来处理ref_table:

SELECT * FROM ref_table WHERE key_column=expr;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
Run Code Online (Sandbox Code Playgroud)

这些是从MySQL手册中逐字复制的:http://dev.mysql.com/doc/refman/5.0/en/using-explain.html

如果您可以发布永远需要的查询,我可以帮助查明减慢速度的问题.另外,请说明您对永远的定义.另外,如果你能提供你的"SHOW CREATE TABLE xxx;" 这些表的语句,我可以帮助您尽可能地优化您的查询.

作为一个可能的改进点,立即跳出来的是"使用临时;使用filesort;".这意味着创建了一个临时表来满足查询(不一定是坏事),并且无法从索引中检索您指定的GROUP BY/ORDER BY,从而导致文件排序.