Mysql在大表上性能缓慢

时间:2012-06-30 16:39:09

标签: mysql performance

我有数百万行的下表:

CREATE TABLE `points` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `DateNumber` int(10) unsigned DEFAULT NULL,
  `Count` int(10) unsigned DEFAULT NULL,
  `FPTKeyId` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`),
  KEY `index3` (`FPTKeyId`,`DateNumber`) USING HASH
) ENGINE=InnoDB AUTO_INCREMENT=16755134 DEFAULT CHARSET=utf8$$

正如您所看到的,我创建了索引。我不知道我做得对,可能不是。 问题是查询执行速度超慢。

我们来一个简单的查询

SELECT fptkeyid, count FROM points group by fptkeyid

我无法获得结果,因为查询因超时而中止(10分钟)。我做错了什么?

4 个答案:

答案 0 :(得分:3)

注意MySQL的愚蠢行为:GROUP BY隐式执行ORDER BY

为了防止这种情况,请明确添加ORDER BY NULL,以防止不必要的排序。

http://dev.mysql.com/doc/refman/5.0/en/select.html说:

  

如果使用GROUP BY,则输出行将根据GROUP BY进行排序   列,就好像您有相同列的ORDER BY一样。避免   对GROUP BY生成的排序开销,添加ORDER BY NULL:

SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;

+

http://dev.mysql.com/doc/refman/5.6/en/group-by-optimization.html说:

  

使用GROUP BY索引的最重要的前提条件是   所有GROUP BY列都引用同一索引中的属性,   并且索引按顺序存储其键(例如,这是一个    BTREE 索引,而不是 HASH 索引。

答案 1 :(得分:1)

我个人会从您的AUTO_INCREMENT价值开始。您已为每个新记录增加{em>增加16,755,134。您的字段值设置为INT UNSIGNED,这意味着值范围为0 to 4,294,967,295(或接近43亿)。这意味着在字段超出数据类型限制之前,您将只有 256,从而影响PRIMARY KEY INDEX的目的。

您可以将数据类型更改为BIGINT UNSIGNED,并且您的值范围为0 to 18,446,744,073,709,551,615(或略高于18.4 quintillion),这样您就可以最多{{1具有此1,100,960,700,983值的(或略多于1.1万亿)唯一值

我首先会问您是否确实需要将AUTO_INCREMENT值设置为如此大的数字,如果没有,那么我建议将其更改为1 (或者至少低一些数字)因为将字段值存储为AUTO_INCREMENT vs INT将在诸如此类的较大表中节省大量磁盘空间。无论哪种方式,您都应该获得更稳定的BIGINT,这有助于改善查询。

答案 2 :(得分:1)

您的查询没有意义:

SELECT fptkeyid, count FROM points group by fptkeyid

你按照fptkeyid进行分组,所以这里的计数没用。应该有一个聚合函数。不是计数字段。接下来,该计数也是一个MySQL函数,这使得对字段使用相同的名称不是非常有用/可取。

你不需要这样的东西:

SELECT fptkeyid, SUM(`count`) FROM points group by fptkeyid

如果没有,请解释您对查询的期望结果。

使用测试数据创建了一个包含50万条记录的数据库,以查看是否可以找到与您的问题相同的内容。这就是解释告诉我的:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  points  index   NULL    index3  10  NULL    433756  

在SUM查询中:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  points  index   NULL    index3  10  NULL    491781   

这两个查询都在一台笔记本电脑(macbook air)上完成,不需要花费很长时间。插入虽然花了一些时间,但几分钟才能获得50万条记录。但检索和计算没有。

我们需要更多完整地回答您的问题。也许数据库的配置是错误的,例如几乎没有分配内存?

答案 3 :(得分:-1)

我认为问题在于您的服务器带宽。拥有一百万行可能至少需要高兆字节带宽。