我有以下查询:
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 :(得分: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 更少的行,这显然会加快速度。
此外,请确保stake
和nickname
上的非聚集索引(按此顺序)。
答案 3 :(得分:2)
这是简单的查询。我认为一切都很好。您可以尝试在'桩'字段上添加索引或将限制降低。