简体   繁体   中英

Why is my mutual friends query so slow?

This query used to run very quickly when my database only had a finite amount of friends in it, however as the user base has grown I've found the query getting exponentially slower.

The schema for my friends table looks like:

friend_id   -   entity_id1  -   entity_id2   -   category 
    1               1                2               1
    2               2                1               1
    3               3                2               1
    4               2                3               1
    5               1                3               1
    6               3                1               1

As we can see above, there is a reciprocal relationship between each friend association, this was implemented to improve the query time for suggested friends.

I am now trying to return mutual friends in my suggested friends payload, however the query takes around 1 second to compile for each user in a while loop, and I only currently have 2000 users...this will be a huge problem as the application scales further.

The query I am currently using is as follows:

SELECT COUNT(*) AS mutual_count
FROM entity
WHERE EXISTS(
    SELECT *
    FROM friends
    WHERE friends.Entity_Id1 = :friendId AND friends.Category <> 4
      AND friends.Entity_Id2 = entity.Entity_Id
  )
  AND EXISTS(
    SELECT *
    FROM friends
    WHERE friends.Entity_Id1 = :userId AND friends.Category <> 4
      AND friends.Entity_Id2 = entity.Entity_Id
  )

Where :userId is the logged in user and :friendId is the user we want to get the mutual friends of. As I said, this query works fine but its extremely slow, how can I optimise it?

You have two heavy subqueries and You selects all columns in both of them. First eliminate one of them - try that:

SELECT COUNT(*) AS mutual_count
FROM entity
WHERE (
    SELECT COUNT(*) > 0
    FROM friends
    WHERE friends.Category <> 4 AND friends.Entity_Id2 = entity.Entity_Id
        AND (friends.Entity_Id1 = :friendId AND friends.Entity_Id1 = :userId)
)

Then I suggest inner join instead of subquery - maybe something like that:

SELECT COUNT(DISTINCT entity.id) AS mutual_count
FROM entity
INNER JOIN friends ON friends.Entity_Id2 = entity.Entity_Id
    AND friends.Category <> 4
    AND (friends.Entity_Id1 = :userId AND friends.Entity_Id1 = :friendId)

I haven't checked it (and I don't know tables structure) so there may be some syntax error - but I hope It will help You somehow.

您有2个相关的子查询,它们是您可以在mysql中获得的最快的查询,两个子查询的最佳索引是:

ALTER TABLE friends ADD KEY (Entity_Id1, Category, Entity_Id2)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM