【发布时间】:2013-02-25 22:07:42
【问题描述】:
我正在设计一个 Web 应用程序,该应用程序有一个相当复杂的查询来搜索用户当前位置附近的点......以及许多其他信息。主 POI 表中大约有 150 万行,与其他四个表保持连接(其他较小的表用于存储与主要兴趣点相关的其他数据)。
在 mysql 控制台中运行查询时,它会在 0.5 秒或更短的时间内返回我正在寻找的数据(达到这一点就足够了 PITA,但我终于弄清楚了我需要在主POI 表来实现它)...但是当我将查询放入我的应用程序并让它通过网络运行(通过 jquery、ajax 和 php pdo 准备语句)时,返回任何内容需要 6-7 秒以上数据...有时长达 18-25 秒。
我可能做错了什么会导致执行需要这么长时间?有什么我需要确保我正在做的事情我可能会以某种方式忘记吗?
这是我的 php 代码的相关 sn-p(非常简单),其中实际发生了减速:
$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)
【问题讨论】:
-
你能告诉我们:查询,它是来自 MySQL 客户端的定时执行,运行它的实际代码,以及证明 PHP 运行查询正在花费你认为它花费的时间的查询日志?
-
我没有实际的日志...我正在使用 ChromePhp 插件并记录了准备之前、准备之后和执行之后的时间。准备时间为 0 秒,执行时间不同(但通常超过 6-7 秒)。
-
我将使用实际查询编辑我的帖子,请稍等
-
实际上,我宁愿不发布查询......至少不是整个事情。是否有删除生产名称/变量的约定?
-
不,不是真的...当我在 mysql 中运行查询时,它会在不到一秒的时间内返回数据。当我从 php 运行它时(无论它是否是准备好的语句),它需要 3-6 倍的时间(有时甚至更长)。我不明白这如何表明真正的问题涉及我的索引...如果是这样的话,在 mysql 中运行需要很长时间...不是吗?
标签: php mysql pdo prepared-statement