0

我正在设计一个 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)
4

1 回答 1

3

在控制台中,尝试以这种方式运行它

SELECT SQL_NO_CACHE t.treasureID...

和这个

EXPLAIN SELECT t.treasureID...

如果它运行缓慢并且解释显示很多行 - 问题在于查询本身。
如果即使没有缓存它也运行得很快 - 尝试使用准备好的语句
的控制台版本 如果差异仍然存在(没有准备好的控制台,准备慢的控制台) - 分析两个查询并查看你可以从分析结果中得到什么:

set profiling=1;
...run your queries
show profiles;
show profile for query 1;
show profile for query 2;

也尝试与 ATTR_EMULATE_PREPARES 一起玩,但我觉得它不会有太大帮助。
还要确保 PHP 端没有其他需要时间的代码

于 2013-02-26T05:36:11.883 回答