如何优化此查询?

时间:2009-08-14 10:54:45

标签: sql mysql

我有以下查询:

SELECT `masters_tp`.*, `masters_cp`.`cp` as cp, `masters_cp`.`punti` as punti
FROM (`masters_tp`)
LEFT JOIN `masters_cp` ON `masters_cp`.`nickname` = `masters_tp`.`nickname`
WHERE `masters_tp`.`stake` = 'report_A'
AND `masters_cp`.`stake` = 'report_A'
ORDER BY `masters_tp`.`tp` DESC, `masters_cp`.`punti` DESC
LIMIT 400;

此查询是否存在可能影响服务器内存的问题?

以下是EXPLAIN的输出

| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows  | Extra                                        |
+----+-------------+------------+------+---------------+------+---------+------+-------+----------------------------------------------+
|  1 | SIMPLE      | masters_cp | ALL  | NULL          | NULL |    NULL | NULL |  8943 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | masters_tp | ALL  | NULL          | NULL |    NULL | NULL | 12693 | Using where                                  | 

4 个答案:

答案 0 :(得分:6)

运行以EXPLAIN为前缀的相同查询,并将输出添加到您的问题中 - 这将显示您正在使用的索引和正在分析的行数。

您可以从解释中看到没有使用索引,并且必须查看数千行才能获得结果。尝试在用于执行连接的列上添加索引,例如昵称和赌注:

ALTER TABLE masters_tp ADD INDEX(nickname),ADD INDEX(stake);
ALTER TABLE masters_cp ADD INDEX(nickname),ADD INDEX(stake);

(我假设列可能有重复的值,如果没有,请使用UNIQUE而不是INDEX)。有关详细信息,请参阅MySQL manual

答案 1 :(得分:5)

通过仅显式命名您实际需要的表中的字段来替换“masters_tp。*”位。即使你需要它们,也要将它们全部命名。

答案 2 :(得分:5)

实际上没有理由在这里做left join。您正在使用过滤器来消除连接的任何左边。试试这个:

SELECT 
    `masters_tp`.*, 
    `masters_cp`.`cp` as cp, 
    `masters_cp`.`punti` as punti
FROM 
    `masters_tp`
    INNER JOIN `masters_cp` ON 
        `masters_tp`.`stake` = `masters_cp`.stake`
        and `masters_tp`.`nickname` = `masters_cp`.`nickname`
WHERE 
    `masters_tp`.`stake` = 'report_A'
ORDER BY 
    `masters_tp`.`tp` DESC, 
    `masters_cp`.`punti` DESC
LIMIT 400;

inner join往往比left join更快。查询可以使用谓词(也称为where子句)限制必须连接的行数。这意味着数据库可能正在处理 lot 更少的行,这显然会加快速度。

此外,请确保stakenickname上的非聚集索引(按此顺序)。

答案 3 :(得分:2)

这是简单的查询。我认为一切都很好。您可以尝试在'桩'字段上添加索引或将限制降低。