2012-07-31 50 views
0
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查詢?

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

回答

0

添加此指數:

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

什麼是力指數? – TIMEX 2012-07-31 02:51:00

0

通過對一組的順序由導致臨時表+文件排序其殺害你的表現。

嘗試子查詢?

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