2017-02-14 77 views
0

everyone。这是我的MySQL服务器中的一个问题。
我有一张约40,000,000行和10列的表格。
它的大小约为4GB,引擎是innodb。
它是一个主数据库,只执行一个这样的sql。在mysql中拆分表的性能

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

约99%sqls执行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:
我也试图与固态硬盘和硬盘驱动器不同的计算机上,但并没有帮助过。

回答

0

尝试使用mysql代理将数据库拆分为一些mysql实例,就像mysql-proxy或haproxy而不是一个mysql实例。也许你可以有很棒的表现。

+0

但是我的公司没有太多的预算用于更多的实例。有什么办法可以尝试吗?多谢 –

+0

你可以尝试备份一些数据并删除它们,如果你的业务被允许的话 –

+0

或者你可以将你的表分成7个或更多的表。每天阅读一张表并备份并清除其他表。 –

0

拆分表格不太可能有所帮助。同上PARTITIONing

让我们来计算磁盘命中。我会跳过计算BTrees中的非叶节点;他们往往被缓存;我会统计数据和索引中的叶节点;他们往往不被缓存。

IODKU作用:

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

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

让我们考虑一个变化...如果你摆脱了id?你需要id其他地方吗?既然你有一个UNIQUE的钥匙,可能是PK。这是用PRIMARY KEY(user_id)替换你的两个索引。现在计数:

  1. 1读
  2. 如果UPDATE,0读,写1
  3. 如果INSERT,0读取,写入0

总计:1次的读,写1。 2/3和以前一样多。更好,但仍不是很好。

缓存

多少RAM你有?
innodb_buffer_pool_size的值是多少?
SHOW TABLE STATUS - 什么是Data_lengthIndex_length

我怀疑buffer_pool不够大,可能会引发。如果你有超过4GB的内存,使它大约占内存的70%。

其他

因为你似乎是I/O密集型

固态硬盘应该有显著帮助。你能分辨出你是I/O绑定还是CPU绑定?

一次更新多少行?多久时间?它是批处理,还是一次一个?这里可能会有重大改进。

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

是否涉及交易?

师父有问题吗?奴隶?都?我不想以这样的方式修理师父,弄乱奴隶。

+0

非常感谢。 我没有考虑删除自动递增键。这太棒了。 1.我试图改变innodb_buffer_pool_size的值,但没有帮助。 2.我也尝试了你的建议,使数据成批,这很好。 3.由于数据原因BIGINT无法更改。 4.并没有事务involed。 5.只有主人有问题。 –

+0

完整的SQL是这样的。 'INSERT DELAYED INTO mytable(user_id,identifier,account_id,top_speed,total_chars,total_time,keystrokes,avg_speed,country_code)VALUES(%s,%s,%s,%s,%s,%s,%s,%s, %s)ON DUPLICATE KEY UPDATE account_id =%s,top_speed =%s,total_chars =%s,total_time =%s,keystrokes =%s,avg_speed =%s“ –

+0

如果复制是”基于行“的,那么一些磁盘命中只发生在Master中; Slave不需要在插入和更新之间重新决定,这可以解释为什么只有Master有问题。 –