2012-02-01 8 views
-1

У меня есть две таблицы: users и user_friends с отражающим соединением 1: 1 на столе users. (т. е. user_friends записей, как [user_id, friend_id], [friend_id, user_id]).Можно ли улучшить производительность этого SQL-запроса?

Скажем, у меня есть пользователь, называемый «я». То, что я пытаюсь сделать, это найти всех пользователей, у которых есть общий друг с «я» и которые отвечают другим простым критериям в таблице пользователей. Это лучшее, что я придумал до сих пор, которое длится около 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

если вы собираетесь downvote это могли бы вы оставить комментарий говоря, почему – galarant

+0

Это локализованный вопрос, который не имеет однозначный ответ. И ваше название заставляет это звучать так, как будто вы хотите, чтобы другие люди выполняли вашу работу. Между прочим, я не сделал этого. –

+0

ok Justin за отзыв – galarant

ответ

3

Есть несколько способов улучшить ваш запрос.

  1. Используйте JOIN вместо фильтров из двух таблиц.
  2. Перестройте свой AND s так, чтобы более простые короткие замыкания были быстрее, что останавливало подзапрос от того, чтобы бегать так часто.

Код:

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} 
) 
) 
; 
Смежные вопросы