我正在设计一个Web应用程序,它具有相当复杂的查询,可以搜索用户当前位置附近的点...以及其他一些信息。主POI表中大约有150万行,它们连接到其他四个表(其他较小的表用于与主要兴趣点相关的其他数据)。
在mysql控制台中运行查询时,它会在0.5秒或更短的时间内返回我正在查找的数据(到达那一点就足够了PITA,但我终于找到了我需要的主要指标使POI表发生的事情)...但是当我将查询放入我的应用程序并通过网络运行时(通过jquery,ajax和php pdo预处理语句),返回任何内容需要6-7秒数据...有时长达18-25秒。
我可能做错了什么会导致执行花费这么长时间?有什么我需要确保我这样做,我可能会忘记某种程度?
这是我的PHP代码的相关片段(非常简单),其中实际发生了减速:
$qry = "...";
$data = array(xxx); // user's lat/lon and other data we need
$sth = $this -> ci -> prepare($qry);
$sth -> execute($data);
对于记录,将此作为未准备好的声明运行并没有更好。事实上,它实际上有点慢......
请帮助我,我整天都在扯掉头发。我想过,一旦我最终得到优化的查询它将解决问题,但事实证明,显然不是这样......mysql> select
t.treasureID, t.buriedByUserID, t.lockLevel, t.currentGoldValue, t.initialSilverValue,
t.burySeen, t.initialGoldValue, t.prize1, t.buryPerkID, t.decoyOf,
t.unlockAttempts, t.unlockedByKeypad, t.unlockedByUserID, t.prizeID,
p.prizeDesc, p.validFrom, p.validUntil, p.sponsor, p.prizeName,
userB.displayName as bDisplayName, s.sponsorID, s.sponsorName, pb.perkName,
(DEGREES( ACOS( SIN( RADIANS( 40.6846 ) ) * SIN( RADIANS( t.latitude ) ) + COS( RADIANS( 40.6846 ) ) * COS( RADIANS( t.latitude ) ) * COS( RADIANS( -76.19613 - t.longitude ) ) ) ) * 60 * 1.1515 ) AS distance
from treasures t
left join prizes p on t.prizeID=p.prizeID
left join userInfo userB on userB.userID=t.buriedByUserID
left join sponsors s on p.sponsorID=s.sponsorID
left join perksB pb on t.buryPerkID=pb.perkID
where
t.unlockedByUserID=-1 and
t.buriedByUserID<>1011 and
t.isGlobal=0 and
t.latitude between 40.467351088803 and 40.901848911197 and
t.longitude between -76.483560028513 and -75.908699971487 and
((1361820374 > p.validFrom and 1361820374 < p.validUntil) or p.validUntil is null)
having distance < 15
order by distance asc
limit 0, 50;
+------------+----------------+-----------+------------------+--------------------+----------+------------------+--------+------------+---------+----------------+------------------+------------------+---------+---------------------------------------------------------------------------------------------------------------------------+------------+------------+---------------+-----------------+--------------+-----------+--------------+----------+---------------------+
| treasureID | buriedByUserID | lockLevel | currentGoldValue | initialSilverValue | burySeen | initialGoldValue | prize1 | buryPerkID | decoyOf | unlockAttempts | unlockedByKeypad | unlockedByUserID | prizeID | prizeDesc | validFrom | validUntil | sponsor | prizeName | bDisplayName | sponsorID | sponsorName | perkName | distance |
+------------+----------------+-----------+------------------+--------------------+----------+------------------+--------+------------+---------+----------------+------------------+------------------+---------+---------------------------------------------------------------------------------------------------------------------------+------------+------------+---------------+-----------------+--------------+-----------+--------------+----------+---------------------+
+------------+----------------+-----------+------------------+--------------------+----------+------------------+--------+------------+---------+----------------+------------------+------------------+---------+---------------------------------------------------------------------------------------------------------------------------+------------+------------+---------------+-----------------+--------------+-----------+--------------+----------+---------------------+
50 rows in set (0.78 sec)
答案 0 :(得分:3)
在控制台中,尝试以这种方式运行
SELECT SQL_NO_CACHE t.treasureID...
和这个
EXPLAIN SELECT t.treasureID...
如果它运行缓慢且解释显示很多行 - 问题是查询本身
如果即使没有缓存也能快速运行 - 请尝试使用console version of prepared statements
如果差异仍然存在(控制台没有准备好快速,控制台准备慢) - 配置两个查询并查看从分析结果中可以获得的内容:
set profiling=1;
...run your queries
show profiles;
show profile for query 1;
show profile for query 2;
也尝试使用ATTR_EMULATE_PREPARES,但我觉得它不会有多大帮助。
还要确保PHP方面没有其他代码需要花费时间