我之前问过一个关于如何分析大型数据集的问题 (how can I analyse 13GB of data)。一个有前途的回应是使用自然键将数据添加到 MySQL 数据库中,从而利用 INNODB 的聚簇索引。
我已将数据添加到数据库中,其架构如下所示:
TorrentsPerPeer
+----------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------------+------+-----+---------+-------+
| ip | int(10) unsigned | NO | PRI | NULL | |
| infohash | varchar(40) | NO | PRI | NULL | |
+----------+------------------+------+-----+---------+-------+
这两个字段共同构成了主键。
此表代表已知的点下载种子的实例。我希望能够提供有关在同行中可以找到多少种子的信息。我将绘制我看到的种子数量的频率直方图(例如,20 个同行有 2 个种子,40 个同行有 3 个,...)。
我编写了以下查询:
SELECT `count`, COUNT(`ip`)
FROM (SELECT `ip`, COUNT(`infohash`) AS `count`
FROM TorrentsPerPeer
GROUP BY `ip`) AS `counts`
GROUP BY `count`;
这是子选择的EXPLAIN
:
+----+-------------+----------------+-------+---------------+---------+------------+--------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_length | ref | rows | Extra |
+----+-------------+----------------+-------+---------------+---------+------------+--------+----------+-------------+
| 1 | SIMPLE | TorrentPerPeer | index | [Null] | PRIMARY | 126 | [Null] | 79262772 | Using index |
+----+-------------+----------------+-------+---------------+---------+------------+--------+----------+-------------+
我似乎无法为完整查询执行 EXPLAIN
,因为它花费的时间太长了。这bug表明这是因为它首先运行子查询。
此查询当前正在运行(已经运行了一个小时)。 top
报告 mysqld
仅使用了大约 5% 的可用 CPU,而其 RSIZE
正在稳步增加。我在这里的假设是服务器正在 RAM 中构建用于完成查询的临时表。
那么我的问题是;我怎样才能提高这个查询的性能?我应该以某种方式更改查询吗?我一直在更改 my.cnf
文件中的服务器设置以增加 INNODB 缓冲池大小,我应该更改任何其他值吗?
如果重要的话,该表有 79'262'772 行深,占用大约 8GB 的磁盘空间。我不希望这是一个简单的问题,也许“耐心”是唯一合理的答案。
编辑 只是补充一下,查询已经完成,耗时 105 分钟。这并非难以忍受,我只是希望有所改进。
最佳答案
我的直觉是,使用 unsigned int 和 varchar 40(尤其是 varchar!),您现在拥有一个巨大的主键,它使您的索引文件太大而无法容纳您为 Innodb_buffer_pool 提供的任何 RAM。这将使 InnoDB 在搜索时不得不依赖磁盘来交换索引页,这是大量的磁盘寻道而不是大量的 CPU 工作。
我为类似问题所做的一件事是使用介于真正自然键和代理键之间的东西。我们将采用实际上唯一的 2 个字段(其中一个也是 varchar),并且在应用程序层中将生成固定宽度的 MD5 哈希并将其用作键。是的,这意味着应用程序需要做更多的工作,但它会生成更小的索引文件,因为您不再使用任意长度的字段。
或者,您可以只使用具有大量 RAM 的服务器,看看这是否使索引适合内存,但我总是喜欢将“向其扔硬件”作为最后的手段:)
关于mysql - 使用大型数据集提高 Run-Once 查询的 MySQL 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11469818/