所以,我从来没有理解过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)

我曾希望对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

推荐答案

保罗:

eq_ref

对于前几个表中的每个行组合,将从该表中读取一行.Other than the system and const types, this is the best possible join type.当连接使用索引的所有部分,并且索引是主键或唯一索引时使用.

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

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;

ref

对于前几个表中的每个行组合,将从此表中读取具有匹配索引值的所有行.ref is used if the join uses only a leftmost prefix of the key or if the key is not a PRIMARY KEY or UNIQUE index (in other words, if the join cannot select a single row based on the key value)美元.如果使用的键只与几行匹配,则这是一种很好的联接类型.

ref can be used for indexed columns that are compared using the = or <=> operator. In the following examples, MySQL can use a ref join to process 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;

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

如果你能发布你的forever人的查询,我可以帮助你找出是什么让它变慢了.另外,请具体说明您对forever的定义是什么.此外,如果您可以为这些表提供"show create table xxx;"语句,我可以帮助您尽可能优化查询.

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

Database相关问答推荐

使用存储过程从子表中删除数据

如何高效地存储棋局?

SearchView 在 Android Studio 中显示 Data.entity.Cantact.@85c7ce6

数据库是序列图中的控制器还是边界?

复合主键

便携式(PHPPass)密码哈希.我应该使用它们吗?

Android - SQLite 数据库存储在哪里?

用于 sql server 的免费国家、城市数据库

使 H2 将引用的名称和未引用的名称视为相同

免费的便携式数据库有哪些?

MS Access 迁移的前端?

JavaScript 布尔搜索查询生成器接口库?

我如何知道何时索引列以及使用什么索引?

SQL Server 2008 中的 Open Table go 了哪里?

使用多个数据库模式的 JPA

如何将 SQL Server 数据库图表迁移到另一个数据库?

如何从数据库中解析时间

QSqlDatabase & QSqlQuery 的正确方法是什么?

使用 PHP/MySQL 导入 CSV 数据

Rake aborted... table ‘users’ already exists