【问题标题】:Docker mysql had degraded performance after re-install ubuntu server重新安装 ubuntu 服务器后,Docker mysql 性能下降
【发布时间】:2022-12-09 12:05:05
【问题描述】:

我在 ubuntu 服务器(20.04 lts)上使用 MySQL 作为官方 docker 镜像(Ver 8.0.27)。
由于扩展存储,我重新安装了服务器。
MySQL和ubuntu服务器的版本是一样的。
但是,MySQL 的性能相当下降。

我正在尝试收集 Ehtereum(这是一种加密货币。)网络的地址。
收集的方法很简单。

  1. 获取交易信息。
  2. 提取地址(收件人和发件人)。
  3. 如果地址已经记录在MySQL表中,则忽略它。如果没有记录地址,则记录地址。
  4. 获取下一个交易信息。
  5. 回到2。

    我通过使用 Typescript 中的程序(使用 Node.jsmysql2Web3.js)执行上述循环。
    关于上面列表中第3项的if语句,我使用的是MySQL的唯一约束,而不是Typescript。

    简而言之,首先,制作如下表格,

    CREATE TABLE `addressList`
     (
      `timestampReadable` varchar(32) DEFAULT NULL,
      `timestamp` int DEFAULT NULL,
      `showUpBlock` int DEFAULT NULL,
      `firstTransactionHash` varchar(66) DEFAULT NULL,
      `address` varchar(42) DEFAULT NULL,
      UNIQUE KEY `addressList_address_uindex` (`address`),
      KEY `addressList2_timestamp_index` (`timestamp`),
      KEY `addressList2_firstTransactionHash_index` (`firstTransactionHash`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
    

    并且,在程序中,只运行以下查询。

    INSERT INTO addressList values (123456, 123456, 123456, 'hfuwheohg', 'jhfoiehhfs');
    

    如果地址唯一,则记录地址,如果地址不唯一,则不记录地址。

    当前的记录数量约为 160,000,000~。
    这可能是一个大表,但程序在重新安装之前以实际性能运行。

    所以,我找不到问题的原因。
    为了以防万一,我运行了check table,结果如下图好像没问题。

    Table Op Msg_type Msg_text
    ethereum.addressList check status OK

    我尝试设置一些 MySQL 配置,如下所示。

    SET GLOBAL max_connections=1500;
    SET GLOBAL sort_buffer_size=1024 * 1024 * 1024;
    

    但是,性能并没有提高。
    第一次启动时忘记了MySQL的配置(真后悔)。

    有谁知道如何处理它? 请帮我!

【问题讨论】:

  • 您是否尝试过使用 manpages.ubuntu.com/manpages/xenial/man1/mysqltuner.1.html mysql tuner for ubuntu?系统运行一两天后打开的最大连接数是多少?新存储有可能相当慢吗?
  • 试试设置Set Global innodb_flush_log_at_trx_commit=2看看写入速度有没有变化。但是,如果这是需要的,它将不符合 ACID。我认为您将 soft_buffer_size 和最大连接数设置得太高。总体内存分配是连接数 X 排序缓冲区大小的倍数,加上一些其他缓冲区。由于您只是将更多内容写入 DB,因此软缓冲区可以很小,例如 4K。
  • 请参阅 insert ignore 而不是在应用程序代码中进行检查。还可以考虑将 address 设为主键和/或 NOT NULL。大号innodb_buffer_pool_sizeinnodb_log_file_size 会有所帮助。如果你有容器日志,一些系统配置可能在日志中。

标签: mysql node.js docker ethereum ubuntu-server


【解决方案1】:
  • 如果列不能是NULL,则说NOT NULL
  • 未指定PRIMARY KEY,因此为您生成一个。
  • 如果address从来不是NULL,那么我强烈推荐PRIMARY KEY(address)删除UNQIQUE(address)
  • [潜在设计缺陷] 您使用的是哪种哈希?某些哈希值可以不是想要一个“ci”归类——他们依赖于“A”和“a”是不同的。考虑将散列更改为 ascii_bin。
  • [节省大量空间] 如果散列是十六进制字符串,请考虑转换为二进制。例如,任何标准 UUID 都会从 36 个字节(ascii 字符)缩小到 16 个字节(二进制字符)。
  • (如果我理解数据),你有两个非常被索引的随机值。在继续之前,让我讨论一下它的后果。
  • 如果这些“散列”是以十六进制表示的 256 位数量(仅限数字和字母),则 UNHEX(...) 将其转换为 BINARY(32)。它已经是'二进制',然后只需将它存储在BINARY(32)。 (相对于VARCHAR(66)

每个索引(包括任何UNIQUE 和隐藏的 PK)都存储在“B+树”中。这个结构是有序的,但索引是什么。

如果 INSERTs 大致按时间顺序执行,则 TIMESTAMP 上的索引将具有 BTree“末尾”的所有活动。这样的“热点”很容易被缓存。也就是说,它非常高效,并且无论表大小如何,都不应减慢速度。

如果 firstTransactionHash 是 MD5 或 SHAnnn 或类似的,那么这些值是非常随机的。缓存其 BTree 的块基本上是无用的。因此,在某些时候,下一个 INSERT 所需的“下一个”块不太可能在 RAM 中。这需要一个 I/O。 I/O 很耗时。

我不知道 address 是什么样的,但我怀疑它的索引与上述之一类似。

“随机性”适用于它是 varchar 还是二进制。

缩小表的大小是主要目标。但这只是部分“修复”。最终,你的桌子会再次这么大相对于缓存大小性能会下降。缓存大小由MySQL的innodb_buffer_pool_size控制;当前值是多少?该设置受限于 MySQL 可用 RAM 的很大一部分;你有多少?检查Docker是否在进一步约束其控制下的“ram”。

【讨论】:

  • 感谢你的回复。我会说NOT NULL。我将使用PRIMARY KEY(address) 并删除UNIQUE(address)。关于firstTransactionHash,是以keccak256为基础的十六进制。这是以太坊的规范(reference)。在这种情况下我应该把它转换成二进制吗?
  • 我了解“INSERTfirstTransactionHash,但是表中的“SELECT”和firstTransactionHash怎么样?我正在使用索引来加快“firstTransactionHash”的选择。 address 是一个 42 个字符的十六进制数 (reference)。当前 innodb_buffer_pool_size1024 * 1024 * 1024 * 10(10GB)。我的服务器有 64GB 内存。其他容器正在这台服务器上运行,但是这台服务器的内存有空闲空间。
  • 你能打印一个 keccak256 的例子吗?如果它打印不好,那么让我们看看它的 HEX()。
  • 我添加了一个项目符号项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-21
  • 1970-01-01
  • 2016-09-07
  • 1970-01-01
  • 2011-05-18
  • 2015-04-25
  • 1970-01-01
相关资源
最近更新 更多