【问题标题】:Improving MySQL Performance on a Run-Once Query with a Large Dataset使用大型数据集提高一次性查询的 MySQL 性能
【发布时间】:2012-07-13 06:21:20
【问题描述】:

我之前问过一个关于如何分析大型数据集的问题 (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 分钟。这不是无法忍受的,我只是希望能有所改进。

【问题讨论】:

  • 可以显示表格结构吗?你可以使用explain 命令吗?
  • 每个ip的最大peer数量是多少?
  • @jcho360 表结构在问题中,我没有其他表。我现在将运行 EXPLAIN 并在完成后更新问题。
  • 我的意思是你可以创建一个desc tablename 来查看你的PK、FK、UNIQUES、INDEX
  • @Sebas 这是一个棘手的问题,目前我正在考虑每个唯一的 ip 是一个唯一的对等点。我知道这是一个糟糕的假设,但我希望能够在稍后的分析中消除异常值。

标签: mysql sql database innodb


【解决方案1】:

我的预感是,使用 unsigned int 和 varchar 40(尤其是 varchar!)你现在有一个巨大的主键,它使你的索引文件太大而无法容纳你为 Innodb_buffer_pool 提供的任何 RAM。这将使 InnoDB 在搜索时不得不依赖磁盘来交换索引页,这需要大量的磁盘寻道,而不是大量的 CPU 工作。

我为类似的问题做的一件事是在真正的自然键和代理键之间使用一些东西。我们将采用实际唯一的 2 个字段(其中一个也是 varchar),并在应用程序层中制作一个固定宽度的 MD5 哈希并使用 THAT 作为键。是的,这意味着应用程序需要做更多的工作,但它会生成更小的索引文件,因为您不再使用任意长度的字段。

或者,您可以只使用具有大量 RAM 的服务器,看看这是否使索引适合内存,但我总是喜欢将“扔硬件”作为最后的手段 :)

【讨论】:

    猜你喜欢
    • 2011-12-03
    • 2023-04-08
    • 2019-12-26
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-18
    • 1970-01-01
    相关资源
    最近更新 更多