2016-03-10 6 views
0

MySQL-5.6.24-win32.1432006610Как избежать FileSort при использовании LEFT JOIN + ORDER BY?

У меня есть два простых таблиц, TUser(id, name) и TMessage(id, uid, message). TUser содержит пользователей, а TMessage содержит сообщения пользователей.

SQL, является, как показано ниже, также см: http://sqlfiddle.com/#!9/7f099

CREATE TABLE TUser(
    id  INT UNSIGNED  PRIMARY KEY NOT NULL AUTO_INCREMENT, 
    name VARCHAR(128) NOT NULL 
); 


CREATE TABLE TMessage(
    id  INT UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT, 
    uid  INT UNSIGNED NOT NULL, 
    message VARCHAR(256) NOT NULL 
); 


CREATE INDEX TMessageIndexUid ON TMessage(uid); 

Вставьте некоторые данные:

INSERT INTO TUser (name) VALUES 
    ('jack') 
    ,('rose') 
    ,('peter'); 


INSERT INTO TMessage(uid, message) VALUES 
    (1, 'Hello jack') 
    , (1, 'Jack, how are you') 
    , (1, 'Good morning jack') 
    , (2, 'I love you, rose') 
    , (3, 'Peter, please call back') 
    , (3, 'What are you doing, Peter'); 

При запуске следующей LEFT JOIN + ORDER BY запроса, FileSort показывает в EXPLAIN результате :

EXPLAIN 
SELECT * 
    FROM  TUser 
    LEFT JOIN TMessage 
    ON   TUser.id=TMessage.uid 
    WHERE  TUser.id=3 
    ORDER BY TMessage.id DESC; 



id select_type table type possible_keys key    key_len ref rows Extra 
1 SIMPLE  TUser const PRIMARY;   PRIMARY   4  const 1 Using temporary; Using filesort 
1 SIMPLE  TMessage ref TMessageIndexUid TMessageIndexUid 4  const 2 \N 

Есть что-то неправильно?

ответ

1

FileSort вводится с помощью ORDER BY :

mysql> EXPLAIN 
    -> SELECT * 
    -> FROM  TUser 
    -> LEFT JOIN TMessage 
    -> ON   TUser.id=TMessage.uid 
    -> WHERE  TUser.id=3 
    -> ORDER BY TMessage.id DESC; 
+----+-------------+----------+------------+-------+------------------+------------------+---------+-------+------+----------+---------------------------------+ 
| id | select_type | table | partitions | type | possible_keys | key    | key_len | ref | rows | filtered | Extra       | 
+----+-------------+----------+------------+-------+------------------+------------------+---------+-------+------+----------+---------------------------------+ 
| 1 | SIMPLE  | TUser | NULL  | const | PRIMARY   | PRIMARY   | 4  | const | 1 | 100.00 | Using temporary; Using filesort | 
| 1 | SIMPLE  | TMessage | NULL  | ref | TMessageIndexUid | TMessageIndexUid | 4  | const | 4 | 100.00 | NULL       | 
+----+-------------+----------+------------+-------+------------------+------------------+---------+-------+------+----------+---------------------------------+ 
2 rows in set, 1 warning (0.00 sec) 

mysql> EXPLAIN 
    -> SELECT * 
    -> FROM  TUser 
    -> LEFT JOIN TMessage 
    -> ON   TUser.id=TMessage.uid 
    -> WHERE  TUser.id=3; 
+----+-------------+----------+------------+-------+------------------+------------------+---------+-------+------+----------+-------+ 
| id | select_type | table | partitions | type | possible_keys | key    | key_len | ref | rows | filtered | Extra | 
+----+-------------+----------+------------+-------+------------------+------------------+---------+-------+------+----------+-------+ 
| 1 | SIMPLE  | TUser | NULL  | const | PRIMARY   | PRIMARY   | 4  | const | 1 | 100.00 | NULL | 
| 1 | SIMPLE  | TMessage | NULL  | ref | TMessageIndexUid | TMessageIndexUid | 4  | const | 4 | 100.00 | NULL | 
+----+-------------+----------+------------+-------+------------------+------------------+---------+-------+------+----------+-------+ 
2 rows in set, 1 warning (0.00 sec) 

Поскольку заказ работает на результат LEFT JOIN, я понятия не имею, как избежать этого файла.

Если сменить LEFT JOIN на INNER JOIN допустимо, возможно, это способ обойти, в то время как отсутствует некоторая информация о пользователе, не совпадающая с TMessages.

mysql> EXPLAIN 
    -> SELECT * 
    -> FROM  TUser 
    -> INNER JOIN TMessage 
    -> ON   TUser.id=TMessage.uid 
    -> WHERE  TUser.id=3 
    -> ORDER BY TMessage.id DESC; 
+----+-------------+----------+------------+-------+------------------+------------------+---------+-------+------+----------+-------------+ 
| id | select_type | table | partitions | type | possible_keys | key    | key_len | ref | rows | filtered | Extra  | 
+----+-------------+----------+------------+-------+------------------+------------------+---------+-------+------+----------+-------------+ 
| 1 | SIMPLE  | TUser | NULL  | const | PRIMARY   | PRIMARY   | 4  | const | 1 | 100.00 | NULL  | 
| 1 | SIMPLE  | TMessage | NULL  | ref | TMessageIndexUid | TMessageIndexUid | 4  | const | 2 | 100.00 | Using where | 
+----+-------------+----------+------------+-------+------------------+------------------+---------+-------+------+----------+-------------+ 
2 rows in set, 1 warning (0.00 sec) 
+0

Можно ли избежать FileSort? – Zach

+0

Требуется ли ЗАКАЗАТЬ? –

+0

Сообщение обновлено. Является ли переход на INNER JOIN приемлемым? @Zach –

Смежные вопросы