即使看似正确的索引和足够的内存,查询运行时间也会太长

时间:2013-02-01 17:11:29

标签: mysql query-optimization

我有一张包含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 |
+----+-------------+--------+-------+---------------+-----------+---------+------+---------+---------------------------------+

如何优化此查询。即使在10分钟后,它也不会产生任何输出。

我觉得我已经索引了正确的列并为临时表提供了足够的内存。

2 个答案:

答案 0 :(得分:1)

我不确定这是否会有所帮助,但MySQL一次只能使用一个索引,因此在FileMD5NoCsumMD5上创建索引可能会有所帮助:

KEY `someName` (`NoCsumMD5`, `FileMD5`),

这是一些information on multiple column indexes

  

MySQL可以对测试索引中所有列的查询使用多列索引,或者只测试第一列,前两列,前三列等的查询。如果在索引定义中以正确的顺序指定列,则单个复合索引可以加速同一个表上的多种查询。

简短版本是索引中列的顺序很重要,因为MySQL只能按顺序使用索引(例如,在我上面给出的索引中,它可以测试NoCsumMD5,然后缩小结果使用FileMD5)。

我不确定在这个查询中它会有多大帮助,因为你关心的是FileMD5NULL还是{。}}。

答案 1 :(得分:1)

由于FileMD5在表定义中不是NULL,因此查询可以简化,并且您不需要复合索引@ brendan-long建议(NoCsumMD5索引就足够了):

SELECT NoCsumMD5, Count(*) as cnt 
FROM Sample
GROUP BY NoCsumMD5 
HAVING cnt > 10
ORDER BY cnt DESC;