我有数百万行的下表:
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分钟)。我做错了什么?
答案 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)
我认为问题在于您的服务器带宽。拥有一百万行可能至少需要高兆字节带宽。