简体   繁体   中英

How do I optimize a basic MySQL query with basic inner join?

SELECT au.* 
FROM users au 
INNER JOIN friends fa  ON au.id = fa.to_user_id  
WHERE fa.from_user_id = 369 AND fa.persona_id IN('1241') 
GROUP BY au.id 
ORDER BY id DESC 
LIMIT 0, 9999999999;

Here is the explain

mysql> EXPLAIN SELECT au.* FROM users au INNER JOIN friends fa  ON au.id = fa.to_user_id  WHERE fa.from_user_id = 369 AND fa.persona_id IN('1241') GROUP BY au.id ORDER BY id DESC LIMIT 0, 9999999999;
+----+-------------+-------+-------------+------------------------------------------------------------+------------------------------------+---------+--------------------+------+---------------------------------------------------------------------------------------------------+
| id | select_type | table | type        | possible_keys                                              | key                                | key_len | ref                | rows | Extra                                                                                             |
+----+-------------+-------+-------------+------------------------------------------------------------+------------------------------------+---------+--------------------+------+---------------------------------------------------------------------------------------------------+
|  1 | SIMPLE      | fa    | index_merge | from_user_id,to_user_id,persona_id,from_user_id_persona_id | persona_id,from_user_id_persona_id | 4,8     | NULL               |   49 | Using intersect(persona_id,from_user_id_persona_id); Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | au    | eq_ref      | PRIMARY                                                    | PRIMARY                            | 4       | kjdb.fa.to_user_id |    1 |                                                                                                   |
+----+-------------+-------+-------------+------------------------------------------------------------+------------------------------------+---------+--------------------+------+---------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

I only have 300,000 rows in this table, but it's taking forever. (about .75 seconds to run it)

mysql> desc friends;
+-------------------+------------+------+-----+---------+----------------+
| Field             | Type       | Null | Key | Default | Extra          |
+-------------------+------------+------+-----+---------+----------------+
| id                | int(11)    | NO   | PRI | NULL    | auto_increment |
| from_user_id      | int(11)    | NO   | MUL | NULL    |                |
| to_user_id        | int(11)    | NO   | MUL | NULL    |                |
| persona_id        | int(11)    | NO   | MUL | NULL    |                |
| action_by_user_id | int(11)    | NO   | MUL | NULL    |                |
| is_disabled       | tinyint(1) | NO   |     | 0       |                |
| created_at        | datetime   | YES  |     | NULL    |                |
| updated_at        | datetime   | YES  |     | NULL    |                |
+-------------------+------------+------+-----+---------+----------------+
8 rows in set (0.01 sec)



> desc users;
+---------------------+--------------+------+-----+---------+----------------+
| Field               | Type         | Null | Key | Default | Extra          |
+---------------------+--------------+------+-----+---------+----------------+
| id                  | int(11)      | NO   | PRI | NULL    | auto_increment |
| username            | varchar(255) | NO   | UNI | NULL    |                |
| first_name          | varchar(255) | NO   | MUL | NULL    |                |
| last_name           | varchar(255) | YES  | MUL | NULL    |                |
| email               | varchar(255) | YES  | UNI | NULL    |                |

here are my indexes:

mysql> show indexes from friends;
+-------------------+------------+-------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table             | Non_unique | Key_name                | Seq_in_index | Column_name       | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------------+------------+-------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+
| friends |          0 | PRIMARY                 |            1 | id                | A         |      388926 |     NULL | NULL   |      | BTREE      |         |
| friends |          0 | from_user_id            |            1 | from_user_id      | A         |          17 |     NULL | NULL   |      | BTREE      |         |
| friends |          0 | from_user_id            |            2 | to_user_id        | A         |      388926 |     NULL | NULL   |      | BTREE      |         |
| friends |          0 | from_user_id            |            3 | persona_id        | A         |      388926 |     NULL | NULL   |      | BTREE      |         |
| friends |          1 | to_user_id              |            1 | to_user_id        | A         |       19446 |     NULL | NULL   |      | BTREE      |         |
| friends |          1 | persona_id              |            1 | persona_id        | A         |       32410 |     NULL | NULL   |      | BTREE      |         |
| friends |          1 | action_by_user_id       |            1 | action_by_user_id | A         |        9972 |     NULL | NULL   |      | BTREE      |         |
| friends |          1 | from_user_id_persona_id |            1 | from_user_id      | A         |        9486 |     NULL | NULL   |      | BTREE      |         |
| friends |          1 | from_user_id_persona_id |            2 | persona_id        | A         |       35356 |     NULL | NULL   |      | BTREE      |         |
+-------------------+------------+-------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+

Add this index:

ALTER TABLE friends ADD INDEX ix_from_persona_to (from_user_id,persona_id,to_user_id);

and see if that helps.

If not, you may have to add a FORCE INDEX :

SELECT 
    au.* 
FROM 
    users au 
INNER JOIN 
    friends fa ON au.id = fa.to_user_id  
FORCE INDEX
    (ix_from_persona_to)
WHERE
    fa.from_user_id = 369 AND
    fa.persona_id IN ('1241')
GROUP BY
    au.id 
ORDER BY
    id DESC
LIMIT
    0, 9999999999;

the order by on a group by is causing a temp table + filesort which is killing your performance.

try subselects?

SELECT au.* 
FROM users au 
WHERE au.id IN (
  SELECT DISTINCT fa.to_user_id 
  FRoM friends fa 
  WHERE fa.from_user_id = 369 AND fa.persona_id IN('1241') 
)
ORDER BY id DESC 
LIMIT 0, 9999999999;

then add indexes on friends.from_user_id , persona_id

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