簡體   English   中英

如何使用基本內部聯接優化基本MySQL查詢?

[英]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;

這是解釋

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)

我在此表中只有30萬行,但它將永遠占用。 (大約需要0.75秒才能運行)

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    |                |

這是我的索引:

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      |         |
+-------------------+------------+-------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+

添加此索引:

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

看看是否有幫助。

如果沒有,您可能必須添加一個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;

按group by排序會導致臨時表+文件排序,這會影響您的性能。

嘗試子選擇?

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;

然后在friends.from_user_id,persona_id上添加索引

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM