0

私は、ユーザーの現在の場所の近くのポイントを検索するためのかなり複雑なクエリを持つ Web アプリケーションを設計しています...他のかなりの数の情報とともに。メインの POI テーブルには約 150 万行あり、他の 4 つのテーブルに結合されたままになっています (他の小さなテーブルは、主な関心点に関連する他のデータ用です)。

mysql コンソールでクエリを実行すると、探しているデータが 0.5 秒以内に返されます (その時点まで到達するのは PITA で十分でしたが、メインの POI テーブルで必要なインデックスを最終的に見つけました。それを実現します)...しかし、クエリをアプリに入れ、Web経由で(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...

実行が遅く、explain が多くの行を表示する場合 - 問題はクエリ自体です。キャッシュなしでも高速に実行される場合 -準備済みステートメントのコンソール バージョンを
試してください 違いが続く場合 (準備済みの高速でないコンソール、準備済みの低速のコンソール) - 両方のクエリをプロファイリングし、プロファイリング結果から何が得られるかを確認します。

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 に答える