可以改进此SQL查询的性能吗?

时间:2012-02-01 18:47:50

标签: mysql sql

我有两个表:usersuser_friendsusers表上有1:1反射联接。 (即user_friends条记录类似于[user_id, friend_id][friend_id, user_id])。

让我们说我有一个名为“self”的用户。我想要做的是找到所有与“self”共同拥有共同朋友并且在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

1 个答案:

答案 0 :(得分:3)

有几种方法可以改善您的查询。

  1. 使用JOIN而不是从两个表中过滤。
  2. 重新排列AND,以便更简单的短路更快,停止子查询经常运行。
  3. <强>代码:

    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}
      )
    ) 
    ;