【发布时间】:2014-04-12 11:55:20
【问题描述】:
我有表 A,其中包含 IP 范围(列 startIpNum、endIpNum、locId)和表 A_location(列 locaId 和其他不重要的列)。有以下索引 - A 上的 startIpNum 和 endIpNum,以及 A_location 上的 locId。
问题是有时查询的执行速度非常慢。下面是一个 mysql-slow 日志文件,其中包含两个查询,其中两个查询都不返回。
# Time: 140001 21:18:45
# User@Host: root[root] @ localhost [127.0.0.1]
# Query_time: 0.023001 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 0
SET timestamp=1394367480;
SELECT * FROM A_location AS location, (SELECT * FROM A WHERE (3998482191 BETWEEN startIpNum AND endIpNum) ORDER BY startIpNum DESC LIMIT 1) AS blocks WHERE location.locId = blocks.locId;
# Time: 140309 21:18:45
# User@Host: root[root] @ localhost [127.0.0.1]
# Query_time: 54.893140 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 0
SET timestamp=1394367525;
SELECT * FROM A_location AS location, (SELECT * FROM A WHERE (2463400155 BETWEEN startIpNum AND endIpNum) ORDER BY startIpNum DESC LIMIT 1) AS blocks WHERE location.locId = blocks.locId;
这种行为的原因可能是什么?
解释结果:
更新: 问题解决了,最后查询
ALTER TABLE A ORDER BY startIpNum ASC;
SELECT A_location.* FROM A_location AS location,
(SELECT A.* FROM A as blocks,
(SELECT * FROM A WHERE startIpNum < 24465138 ORDER BY startIpNum DESC LIMIT 1) AS startipnumquery
WHERE blocks.startIpNum = startipnumquery.startIpNum AND blocks.endIpNum > 24465138
ORDER BY blocks.endIpNum ASC LIMIT 1) as subresult
WHERE location.locId = subresult.locId;
【问题讨论】:
-
如果 SQL 查询在 MySQL 中运行缓慢,请使用 EXPLAIN 来了解它们是如何执行的
-
如果我没记错的话(已经有一段时间了!)子选择是在父查询的每一行中执行的。所以最坏的情况是你正在做一个 O(n^2) 操作,其中内部操作包括一个排序,这是可以预见的昂贵的。正如 Mark 所说,
EXPLAIN应该让您更好地了解到底发生了什么。 -
添加了解释截图
-
所以,基本上,如果EXPLAIN部分中id=2下的查询使用filesort,速度很快,但是如果使用WHERE,速度很慢。
-
@Polynomial, subselect,在第一种情况下执行,非常快。我还提供了 EXPLAIN 的
标签: php mysql sql performance geoip