mysql - mysql中的分表性能

标签 mysql performance

大家。这是我的 mysql 服务器出现的问题。
我有一个大约 40,000,000 行和 10 列的表。
大小约为4GB,引擎为innodb。
它是一个主数据库,这样只执行一条sql。

insert into mytable ... on duplicate key update ...

大约 99% 的 sql 执行了 update 部分。

现在服务器变得越来越慢。 我听说分割表可以提高它的性能。然后我在我的个人电脑上尝试,分成10个表,失败,也尝试了100个,也失败。速度反而变慢了。所以我想知道为什么拆分表没有提高性能?

提前致谢。

更多详细信息:

CREATE TABLE my_table (
    id BIGINT AUTO_INCREMENT,
    user_id BIGINT,
    identifier VARCHAR(64),
    account_id VARCHAR(64),
    top_speed INT UNSIGNED NOT NULL,
    total_chars INT UNSIGNED NOT NULL,
    total_time INT UNSIGNED NOT NULL, 
    keystrokes  INT UNSIGNED NOT NULL,
    avg_speed INT UNSIGNED NOT NULL,
    country_code VARCHAR(16), 
    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY(id), UNIQUE KEY(user_id)
);

PS:
我还尝试了带有固态驱动器和硬盘驱动器的不同计算机,但也没有帮助。

最佳答案

拆分表格根本不可能有帮助。 分区也是如此。

让我们计算一下磁盘点击次数。我将跳过计算 BTree 中的非叶节点;它们往往会被缓存;我会统计数据和索引中的叶节点;它们往往不会被缓存。

IODKU 的作用是:

  1. 读取包含任何 UNIQUE 键的索引 block 。就您而言,这可能是 user_id。请提供示例 SQL 语句。 1 读。
  2. 如果在索引中找到 user_id 条目,则从 PK(id) 索引的数据中读取记录并执行 UPDATE,并将第二个 block 保留在 buffer_pool 中,以便最终重写到磁盘。 1 现在阅读,1 稍后写入。
  3. 如果未找到记录,请执行INSERT。需要新行的索引 block 已被读取,因此已准备好插入新条目。同时,表中的“最后一个” block (由于 idAUTO_INCRMENT)可能已被缓存。将新行添加到其中。 0 现在读取,1 稍后写入(UNIQUE)。 (重写“最后” block 会分摊到 100 行,所以我忽略它。)
  4. 最终进行写入。

总计,假设基本上全部采用 UPDATE 路径:2 次读取和 1 次写入。假设 user_id 不遵循简单的模式,我将假设所有 3 个 I/O 都是“随机”的。

让我们考虑一个变体...如果去掉 id 会怎样?您在其他地方还需要 id 吗?由于您有一个 UNIQUE key ,可能是 PK。即将两个索引替换为 PRIMARY KEY(user_id)。现在计数是:

  1. 已阅读 1 次
  2. 如果更新,0 次读取,1 次写入
  3. 如果 INSERT,0 次读取,0 次写入

总计:1 次读取,1 次写入。是以前的 2/3。更好了,但仍然不是很好。

缓存

你有多少内存?
innodb_buffer_pool_size 的值是多少?
显示表状态 -- 什么是Data_lengthIndex_length

我怀疑buffer_pool不够大,可能可以提高。如果您的 RAM 超过 4GB,请将其设置为 RAM 的 70% 左右。

其他

SSD 应该有很大帮助,因为您似乎受到 I/O 限制。您能区分出您是 I/O 密集型还是 CPU 密集型吗?

您一次更新多少行?多久时间?是批量的还是一次一个?这里可能会有显着的改进。

你真的需要BIGINT(8字节)吗? INT UNSIGNED 只有 4 个字节。

是否涉及交易?

主人有问题吗?奴隶?两个都?我不想以弄乱从站的方式修复主站。

关于mysql - mysql中的分表性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42218593/

相关文章:

mysql - MySQL插入语句中Oracle到MySQL时间戳的转换

c# - 在 MySQL 和 C# 中使用表达式设置日期时间字段的异常

php - 如何按字母顺序而不是按数据库中的 ID 顺序显示下拉列表中的元素

java - 比较字符串(文字和数字)的最快方法

STL vector+sort+equality vs. unordered_set vs. using pure set 的性能(内存和速度方面)

c# - 如果数据库中的值发生变化,如何持续更新该值

php mysql加入2个表并从每个组中获取有限的行

c - 每个 mmap/access/munmap 两次 TLB 未命中

c++ - -O3 打开时 SSE 中的段错误

c++ - 在 C++ 中快速添加随机变量