2012-02-01 15 views
-1

usersuser_friendsの2つのテーブルがあり、usersテーブルに1:1の反射結合があります。 (すなわちuser_friendsのレコードは[user_id, friend_id],[friend_id, user_id]のようです)。このSQLクエリのパフォーマンスを改善できますか?

私は「自己」と呼ばれるユーザーがいるとしましょう。私がしようとしているのは、「自己」と共通の友人を持ち、usersテーブルの他の単純な基準を満たすすべてのユーザーを見つけることです。これは私がこれまでに考え出した最高のもので、約18秒で実行されます。

このクエリを改善することはできますか?

SELECT 
    DISTINCT(friend_id) 
FROM 
    user_friends, users 
WHERE 
    users.id != #{self.id} 
AND (
    signed_up IS NOT NULL 
    OR 
    user_id IN (
    SELECT 
     friend_id 
    FROM 
     user_friends 
    WHERE 
     user_id = #{self.id} 
) 
) 
AND 
    users.id = friend_id 
AND 
    relationship_status = 'Single' 
AND 
    current_location_id IS NOT NULL 
; 

さらに、このクエリのEXPLAIN PLANがあります。 「一時的な」テーブルは問題を引き起こしていますか?

*************************** 1. row *************************** 
      id: 1 
    select_type: PRIMARY 
     table: user_friends 
     type: index 
possible_keys: NULL 
      key: PRIMARY 
     key_len: 16 
      ref: NULL 
     rows: 1316316 
     Extra: Using where; Using index; Using temporary 
*************************** 2. row *************************** 
      id: 1 
    select_type: PRIMARY 
     table: users 
     type: eq_ref 
possible_keys: PRIMARY,fk_users_current_location_id 
      key: PRIMARY 
     key_len: 8 
      ref: yoke_int.user_friends.friend_id 
     rows: 1 
     Extra: Using where; Distinct 
*************************** 3. row *************************** 
      id: 2 
    select_type: DEPENDENT SUBQUERY 
     table: user_friends 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 16 
      ref: const,func 
     rows: 1 
     Extra: Using index 
+0

あなたは、これはあなたが – galarant

+0

これは明確な答えを持っていないローカライズされた問題である理由というコメントを残してください可能性がdownvoteしようとしている場合。そして、あなたのタイトルは、他の人にあなたの仕事をしてもらいたいというようなものです。私はそれをダウンホートしませんでした。 –

+0

okジャスティンがフィードバックしてくれてありがとう – galarant

答えて

3

クエリを改善するいくつかの方法があります。

  1. 2つのテーブルのフィルタではなく、JOINを使用してください。
  2. ANDを並べ替えて、単純なものほど短絡が早くなり、サブクエリが頻繁に実行されなくなります。

コード:

SELECT 
    DISTINCT(friend_id) 
FROM 
    user_friends 
    JOIN users on users.id = friend_id 
WHERE 
    users.id != #{self.id} 
AND 
    relationship_status = 'Single' 
AND 
    current_location_id IS NOT NULL 
AND (
    signed_up IS NOT NULL 
    OR 
    user_id IN (
    SELECT 
     friend_id 
    FROM 
     user_friends 
    WHERE 
     user_id = #{self.id} 
) 
) 
; 
関連する問題