【问题标题】:How do I optimize a basic MySQL query with basic inner join?如何使用基本内连接优化基本 MySQL 查询?
【发布时间】:2012-07-31 01:53:32
【问题描述】:
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)

我在这个表中只有 300,000 行,但这需要很长时间。 (运行它大约需要 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      |         |
+-------------------+------------+-------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+

【问题讨论】:

    标签: mysql optimization indexing


    【解决方案1】:

    添加此索引:

    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;
    

    【讨论】:

      【解决方案2】:

      group by 上的 order 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 上添加索引

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-18
        • 2012-02-15
        • 1970-01-01
        • 2013-04-16
        • 1970-01-01
        相关资源
        最近更新 更多