2012-01-20 59 views
5

自分のサイトでオンラインになっているユーザーを追跡する必要があるため、オンラインユーザーのアバターの隣に「オンライン」アイコンを表示することができます。このようにしたときにMySQLクエリが高速になるのはなぜですか?このようにすると遅くなりますか?

これを検出する第1のステップは、ユーザがそのように私はUPDATEクエリにユーザーがページを要求するたびにやって最後に見たときのトラックを維持することです:今

UPDATE `users` 
SET `last_seen` = CURRENT_TIMESTAMP 
WHERE `user_id` = '$user_id' 

右この後、私は実行別のクエリ、私はホームページ上でそれらを表示することができますので、この1つは、特定の基準の下で私のサイトのすべてのユーザーを取得します:

SELECT *, 
(ACOS(SIN(0.7103989219783) * SIN(RADIANS(users.latitude)) + COS(0.7103989219783) * COS(RADIANS(users.latitude)) * COS(RADIANS(users.longitude) - -1.2894447135174)) * 6371) AS SearchRadius 
FROM `users` 
INNER JOIN `profiles` ON (
    users.user_id = profiles.user_id 
) 
WHERE (users.latitude > 38.904216788163 AND users.latitude < 42.501503211837) 
AND (users.longitude > -76.252301637251 AND users.longitude < -71.507178362749) 
AND (ACOS(SIN(0.7103989219783) * SIN(RADIANS(users.latitude)) + COS(0.7103989219783) * COS(RADIANS(users.latitude)) * COS(RADIANS(users.longitude) - -1.2894447135174)) * 6371) < 200 AND users.sex = '1' AND users.seeking = '2' AND users.user_id != '1' AND users.account_status = '1' LIMIT 0, 10 

このクエリの狂気を気にしないが、基本的にはポイントは、私は同じusersから選択していますです私が以前に更新したテーブルing。私は別の後にこれらの2つのクエリのいずれかを実行すると

これらは私が得る時間は以下のとおりです。

1st query: 0.0392 seconds 
2nd query: 1.5396 seconds 

これは、ページの読み込み時間に著しい遅延が発生します。今

私はオンラインユーザーのために別のテーブルを作成し、これに最初のクエリを変更します。

1st query: 0.0411 seconds 
2nd query: 0.0008 seconds 

とページのロードはるかに高速:

UPDATE `online_users` 
SET `last_seen` = CURRENT_TIMESTAMP 
WHERE `user_id` = '$user_id' 

回はこれに変更!

これはなぜですか?私の推測では、テーブルのロックと関係がありますが、詳細を知っているか分かっているか分かりません。

+0

2番目のクエリでも正しい結果が返されますか? –

+1

最初のクエリを使わずに2番目のクエリを実行した方が高速ですか?何らかのI/O問題である可能性があります.MySQLの内部構造ではありませんが、SQLの意味でブロックされているものであってはなりません。同じトランザクション内の同じ接続上にあっても、この場合、コミットされていない変更が表示されるか、変更がすでにコミットされています。 InnoDBまたはMyISAMを使用していますか? –

+0

@Cade Roux 2番目のクエリを単独で実行した場合、それは高速ですが、0.0004というわずかな分だけです。私はMyISAMを使用しています。 – TK123

答えて

1

SELECT *にはlast_seenが含まれているため、MySQLはクエリまたはサブクエリをキャッシュできません。 last_seen以外のすべてのフィールドを明示的に列挙してみることもできます。 InnoDBテーブル上の

(ただし、別々のテーブルonline_usersはあまり意味があります。)

+0

は、last_seenを除くすべての列名を明示的に呼び出そうとしましたが、クエリ時間は同じ長さでした。 – TK123

+0

私たちはもっと賢明です。同じテーブルを更新するだけで、そのテーブルの_all_キャッシュされたクエリデータが削除されます。または、テーブルごとのスレッド割り当てや、ディスクの書き戻しのような不明瞭なものもあります。 –

-4

問合せは、MyISAMテーブルに比べて遅いです。 テーブルのより多くの行がクエリを遅くします。 テーブルのインデックス作成が間違っていると、EXPLAINコマンドで確認してください。

0

クエリがテストの前に数回実行されていると仮定すると、クエリキャッシュの効果が見られる可能性があります。テーブルの更新によってキャッシュが無効になり、強制的にクエリが再度実行されます。別のテーブルを更新することで、それらのキャッシュエントリを壊さないようにします。

+0

これは理にかなっていますが、私の場合、そのクエリは一度しか実行されておらず、それは更新クエリの後です。 '他のコマンドを実行する前に、あなたは' SET SESSIONのquery_cache_type = OFFでこれを確認することができます – TK123

+0

注意。 (これにより、現在の接続のクエリキャッシュのみが無効になります)。 –

関連する問題