【发布时间】:2016-03-10 13:17:53
【问题描述】:
mysql-5.6.24-win32.1432006610
我有两个用于用户消息的表格。
TMessageBody (id, body) 存储消息正文。
TMessage (id, uid, folderId, msgBodyId, subject)
将用户的消息存储在收件箱、发件箱等文件夹中。
创建表 SQL:
create table TMessageBody (
id int unsigned not null primary key auto_increment,
body text not null
);
create table TMessage (
id int unsigned not null primary key auto_increment,
uid int unsigned not null,
folderId int unsigned not null,
msgBodyId int unsigned not null,
subject varchar(256) not null
);
一些测试数据:
insert into TMessageBody
(body) values
('Here is body 1')
,('Here is body 2')
,('Here is body 3')
,('Here is body 4')
,('Here is body 5')
,('Here is body 6')
,('Here is body 7')
,('Here is body 8')
,('Here is body 9')
;
insert into TMessage
(uid, folderId, msgBodyId, subject) values
(1, 999, 1, 'Hello jack')
, (1, 999, 2, 'Jack, how are you')
, (1, 888, 3, 'Good morning jack')
, (2, 888, 4, 'I love you, rose')
, (2, 999, 5, 'I love you, rose')
, (3, 888, 6, 'Peter, please call back')
, (3, 999, 7, 'What are you doing, Peter')
, (3, 999, 8, 'Happy birthday, perter')
, (4, 999, 9, 'Let me know if you are ready')
;
索引:
create index Idx_MsgBodyId on TMessage(msgBodyId);
create index Idx_Uid_FolderId on TMessage(uid, folderId);
1.FileSort 显示folderId 不在WHERE 子句中时
以下查询通过给定的用户 ID 获取所有消息,包括消息正文:
SET @uid=3;
SET @folderId=999;
EXPLAIN
SELECT *
FROM TMessage
INNER JOIN TMessageBody
ON TMessage.msgBodyId=TMessageBody.id
WHERE TMessage.uid=@uid
#AND TMessage.folderId=@folderId
ORDER BY TMessage.id DESC
;
EXPLAIN 结果是:
mysql> EXPLAIN
-> SELECT *
-> FROM TMessage
-> INNER JOIN TMessageBody
-> ON TMessage.msgBodyId=TMessageBody.id
-> WHERE TMessage.uid=@uid
-> #AND TMessage.folderId=@folderId
-> ORDER BY TMessage.id DESC
-> ;
+----+-------------+--------------+--------+--------------------------------+------------------+---------+-------------------------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+--------+--------------------------------+------------------+---------+-------------------------+------+-----------------------------+
| 1 | SIMPLE | TMessage | ref | Idx_MsgBodyId,Idx_Uid_FolderId | Idx_Uid_FolderId | 4 | const | 3 | Using where; Using filesort |
| 1 | SIMPLE | TMessageBody | eq_ref | PRIMARY | PRIMARY | 4 | test.TMessage.msgBodyId | 1 | NULL |
+----+-------------+--------------+--------+--------------------------------+------------------+---------+-------------------------+------+-----------------------------+
2 rows in set (0.00 sec)
2.当folderId在WHERE子句中时,FileSort消失
除了 WHERE 子句之外,查询与上面的查询相同:
SET @uid=3;
SET @folderId=999;
EXPLAIN
SELECT *
FROM TMessage
INNER JOIN TMessageBody
ON TMessage.msgBodyId=TMessageBody.id
WHERE TMessage.uid=@uid
AND TMessage.folderId=@folderId
ORDER BY TMessage.id DESC
;
EXPLAIN 结果是:
mysql> EXPLAIN
-> SELECT *
-> FROM TMessage
-> INNER JOIN TMessageBody
-> ON TMessage.msgBodyId=TMessageBody.id
-> WHERE TMessage.uid=@uid
-> AND TMessage.folderId=@folderId
-> ORDER BY TMessage.id DESC
-> ;
+----+-------------+--------------+--------+--------------------------------+------------------+---------+-------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+--------+--------------------------------+------------------+---------+-------------------------+------+-------------+
| 1 | SIMPLE | TMessage | ref | Idx_MsgBodyId,Idx_Uid_FolderId | Idx_Uid_FolderId | 8 | const,const | 2 | Using where |
| 1 | SIMPLE | TMessageBody | eq_ref | PRIMARY | PRIMARY | 4 | test.TMessage.msgBodyId | 1 | NULL |
+----+-------------+--------------+--------+--------------------------------+------------------+---------+-------------------------+------+-------------+
2 rows in set (0.00 sec)
问题:
这两个查询的区别在于folderId 列是否在WHERE 子句中。根据 EXPLAIN 结果,两个查询都使用Idx_Uid_FolderId 索引。我想知道为什么一个显示 FileSort 而另一个没有。
更新
尝试在第一个查询中使用ORDER BY TMessage.folderId, TMessage.id DESC。但是 Using filesort 仍然存在于 EXPLAIN 结果中。
mysql> EXPLAIN
-> SELECT *
-> FROM TMessage
-> INNER JOIN TMessageBody
-> ON TMessage.msgBodyId=TMessageBody.id
-> WHERE TMessage.uid=@uid
-> #AND TMessage.folderId=@folderId
-> ORDER BY TMessage.folderId, TMessage.id DESC
-> ;
+----+-------------+--------------+--------+--------------------------------+------------------+---------+-------------------------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+--------+--------------------------------+------------------+---------+-------------------------+------+-----------------------------+
| 1 | SIMPLE | TMessage | ref | Idx_MsgBodyId,Idx_Uid_FolderId | Idx_Uid_FolderId | 4 | const | 3 | Using where; Using filesort |
| 1 | SIMPLE | TMessageBody | eq_ref | PRIMARY | PRIMARY | 4 | test.TMessage.msgBodyId | 1 | NULL |
+----+-------------+--------------+--------+--------------------------------+------------------+---------+-------------------------+------+-----------------------------+
2 rows in set (0.06 sec)
【问题讨论】: