我有一张包含300万行和6列的表格。
| Sample | CREATE TABLE `sample` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`FileMD5` varchar(32) NOT NULL,
`NoCsumMD5` varchar(32) NOT NULL,
`SectMD5` varchar(32) NOT NULL,
`SectNoResMD5` varchar(32) NOT NULL,
`ImpMD5` varchar(32) NOT NULL,
`Overlay` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`ID`),
KEY `FileMD5` (`FileMD5`),
KEY `NoCsumMD5` (`NoCsumMD5`)
) ENGINE=InnoDB AUTO_INCREMENT=3073630 DEFAULT CHARSET=latin1 |
mysql> SHOW VARIABLES LIKE 'tmp_table_size';
+----------------+----------+
| Variable_name | Value |
+----------------+----------+
| tmp_table_size | 16777216 |
+----------------+----------+
1 row in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'max_heap_table_size';
+---------------------+----------+
| Variable_name | Value |
+---------------------+----------+
| max_heap_table_size | 16777216 |
+---------------------+----------+
1 row in set (0.00 sec)
mysql> explain SELECT NoCsumMD5,Count(FileMD5)
FROM Sample GROUP BY NoCsumMD5
HAVING Count(FileMD5) > 10 ORDER BY Count(FileMD5) Desc ;
+----+-------------+--------+-------+---------------+-----------+---------+------+---------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+-----------+---------+------+---------+---------------------------------+
| 1 | SIMPLE | Sample | index | NULL | NoCsumMD5 | 34 | NULL | 2928042 | Using temporary; Using filesort |
+----+-------------+--------+-------+---------------+-----------+---------+------+---------+---------------------------------+
我觉得我已经索引了正确的列并为临时表提供了足够的内存。
答案 0 :(得分:1)
我不确定这是否会有所帮助,但MySQL一次只能使用一个索引,因此在FileMD5
和NoCsumMD5
上创建索引可能会有所帮助:
KEY `someName` (`NoCsumMD5`, `FileMD5`),
这是一些information on multiple column indexes:
MySQL可以对测试索引中所有列的查询使用多列索引,或者只测试第一列,前两列,前三列等的查询。如果在索引定义中以正确的顺序指定列,则单个复合索引可以加速同一个表上的多种查询。
简短版本是索引中列的顺序很重要,因为MySQL只能按顺序使用索引(例如,在我上面给出的索引中,它可以测试NoCsumMD5
,然后缩小结果使用FileMD5
)。
我不确定在这个查询中它会有多大帮助,因为你关心的是FileMD5
是NULL
还是{。}}。
答案 1 :(得分:1)
由于FileMD5
在表定义中不是NULL,因此查询可以简化,并且您不需要复合索引@ brendan-long建议(NoCsumMD5索引就足够了):
SELECT NoCsumMD5, Count(*) as cnt
FROM Sample
GROUP BY NoCsumMD5
HAVING cnt > 10
ORDER BY cnt DESC;