我已生成查询
select
mailsource2_.file as col_0_0_,
messagedet0_.messageId as col_1_0_,
messageent1_.mboxOffset as col_2_0_,
messageent1_.mboxOffsetEnd as col_3_0_,
messagedet0_.id as col_4_0_
from MessageDetails messagedet0_, MessageEntry messageent1_, MailSourceFile mailsource2_
where messagedet0_.id=messageent1_.messageDetails_id
and messageent1_.mailSourceFile_id=mailsource2_.id
order by mailsource2_.file, messageent1_.mboxOffset;
说明没有使用完整扫描和索引:
+----+-------------+--------------+--------+------------------------------------------------------+---------+---------+--------------------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys |key | key_len | ref | rows | Extra |
+----+-------------+--------------+--------+------------------------------------------------------+---------+---------+--------------------------------------+------+----------------------------------------------+
| 1 | SIMPLE | mailsource2_ | index | PRIMARY |file | 384 | NULL | 1445 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | messageent1_ | ref | msf_idx,md_idx,FKBBB258CB60B94D38,FKBBB258CBF7C835B8 |msf_idx | 9 | skryb.mailsource2_.id | 2721 | Using where |
| 1 | SIMPLE | messagedet0_ | eq_ref | PRIMARY |PRIMARY | 8 | skryb.messageent1_.messageDetails_id | 1 | |
+----+-------------+--------------+--------+------------------------------------------------------+---------+---------+--------------------------------------+------+----------------------------------------------+
CREATE TABLE `mailsourcefile` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`file` varchar(127) COLLATE utf8_bin DEFAULT NULL,
`size` bigint(20) DEFAULT NULL,
`archive_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `file` (`file`),
KEY `File_idx` (`file`),
KEY `Archive_idx` (`archive_id`),
KEY `FK7C3F816ECDB9F63C` (`archive_id`),
CONSTRAINT `FK7C3F816ECDB9F63C` FOREIGN KEY (`archive_id`) REFERENCES `archive` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1370 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
我还有文件和mboxOffset的索引。 SHOW FULL PROCESSLIST表示mysql正在排序结果,需要花费几分钟时间。结果集大小为5M记录。我该如何优化呢?
答案 0 :(得分:3)
优化总是很棘手。为了缩短你的执行时间,我想你可能需要做一些一些的预烹饪。
如果文件名相似,(例如/ path / to / file / 1,/ path / to / file / 2),对它们进行排序将意味着很多字节比较,可能由unicode编码加以复制。我会在插入时计算文件名的哈希值(例如MD5()),然后使用它进行排序。
如果文件已经很好地分发(例如postfix spool名称),你可能需要在插入时提出一些方案:
答案 1 :(得分:3)
不要认为在查询本身中有很多优化要做。连接会使它更具可读性,但现在iirc mysql完全能够检测到这些类型的构造并计划连接本身。
有必要增加tmp_table_size和max_heap_table_size,以允许此查询的结果集保留在内存中,而不必将其写入磁盘。
内存临时表的最大大小是tmp_table_size和max_heap_table_size值的最小值
http://dev.mysql.com/doc/refman/5.5/en/internal-temporary-tables.html
解释中的“using temporary”表示它正在使用临时表(请参阅上面的链接) - 由于数据量很大,可能会将其写入磁盘(再次参阅上面的链接了解更多信息)在此)。 单独的文件列是1到384个字节之间的任何位置,因此我们将一半用于估算并忽略其余列,这会导致结果集中每行192个字节。
1445 * 2721 = 3,931,845 rows
* 192 = 754,914,240 bytes
/ 1024 ~= 737,221 kb
/ 1024 ~= 710 mb
这肯定比max_heap_table_size(16,777,216字节)更多,并且最有可能超过tmp_table_size。
不必将这样的结果写入磁盘肯定会提高速度。
祝你好运!答案 2 :(得分:1)
正如@raheel shan上面所说,你可能想尝试一些JOIN
:
select
mailsource2_.file as col_0_0_,
messagedet0_.messageId as col_1_0_,
messageent1_.mboxOffset as col_2_0_,
messageent1_.mboxOffsetEnd as col_3_0_,
messagedet0_.id as col_4_0_
from
MessageDetails messagedet0_
inner join
MessageEntry messageent1_
on
messagedet0_.id = messageent1_.messageDetails_id
inner join
MailSourceFile mailsource2_
on
messageent1_.mailSourceFile_id = mailsource2_.id
order by
mailsource2_.file,
messageent1_.mboxOffset
如果钥匙关闭,我很抱歉,但我想我已经传达了这一点。
答案 3 :(得分:0)
使用类似
的连接编写查询选择
mailsource2_.file为col_0_0_, messagedet0_.messageId为col_1_0_, messageent1_.mboxOffset为col_2_0_, messageent1_.mboxOffsetEnd为col_3_0_, messagedet0_.id为col_4_0_
<强>从强> MessageDetails m0
内部联接 MessageEntry m1 在强> m0.id = m1.messageDetails_id
内部联接 MailSourceFile m2 在强> m1.mailSourceFile_id = m2.id
按排序 m2_.file, m1_.mboxOffset;
看到你解释我发现了3件我觉得不好的东西
额外列中的1个文件排序
类型列中的2个索引
3密钥长度为384
如果减少密钥长度,可以快速检索,考虑使用的字符集和部分索引
在这里你可以为order by做强制索引并使用index for join(创建适当的多列索引并分配它们)记住它总是很好,在同一个表中存在列的顺序
索引类型表示它正在扫描整个索引列,这是不好的