2009-08-14 106 views
1

我有以下查询:如何优化此查询?

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         | 
+0

我们不可能在没有更多信息的情况下回答这个问题。也许关于表格的一些信息以及它们中有多少数据? – scheibk 2009-08-14 10:56:54

回答

2

这是简单的查询。我认为一切都很好。您可以尝试在“股份”字段中添加索引或降低限制。

6

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

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

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

(我假定列有可能重复值,如果没有,使用唯一的,而不是INDEX)。有关更多信息,请参阅MySQL manual

+0

结果上EXPLAIN ID = 1 SELECT_TYPE = SIMPLE 表= masters_cp 类型= ALL possible_keys = NULL 键= NULL key_len = NULL REF =空 行= 8943 额外=使用其中;使用临时;使用文件排序 ID = 1 SELECT_TYPE = SIMPLE 表= masters_tp 类型= ALL possible_keys = NULL 键= NULL key_len = NULL REF = NULL 行数= 12693 额外=使用其中 – insic 2009-08-14 11:07:19

+0

感谢您的帮助,我现在真的很慢,我不能重写查询。除此之外,我还需要阅读如何为MySQL连接索引 – insic 2009-08-14 11:47:22

5

通过明确命名您实际需要的表中的字段来替换“masters_tp。*”位。即使你需要他们,把他们全部命名。

+0

,谢谢我会这样做。 – insic 2009-08-14 11:51:17

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子句)。这意味着数据库可能会处理更少的行,这显然会加快速度。

此外,请确保您有一个非聚集索引stakenickname(按此顺序)。

+0

他实际上可能希望左连接的关键是将该条件从何处转移到连接处。你现在是对的,由于代码错误,它没有返回一个左连接。 – HLGEM 2009-08-14 19:27:16