9 mysql database linux performance insert
我知道这个问题一直被问到.但是,对于非常具体的情况,这是一个非常具体的问题.希望你能够帮助我.
我运行一个日志数据库,大约有10个表.存储实际日志条目的主表有大约30个字段,其中5个是可搜索的.我说数据库最近变得中等大小,因为我们在该表中达到了2亿条目.其他表存储公共数据,其中最大的一个有4个字段,全部可搜索,有近100万个条目.所有其他表每个包含少于10万条记录.
插入物有尖峰.我每天凌晨2点得到前一天的格式(格式很差的)csv文件,直到上午8点才将它们(大约20个文件,每个10万行)插入到数据库中.然后我在工作日期间得到的选择很少(可能每天约1000个).然后冲洗并重复.
SELECT查询非常简单,因为它们主要由一个或两个GROUP BY语句组成.搜索此数据库的人想要立即获得结果,因此我在主表中有5个多列索引,这有助于我的精确搜索,目前,SELECT性能非常好.到目前为止,没有查询超过0.1秒.有一些报道,但这些生成大约需要10秒钟,这是可以接受的.
目前我有一个C程序,我写的是读取CSV文件中的数据,清理它,并按照每个INSERT查询分批插入1000行.这些INSERT并不完全愚蠢,因为我需要获取公共数据,看看它是否已经存在于其他表中,如果不存在则插入它,如果存在则将其缓存.它还以每秒插入的记录数量的形式提供了性能数据.这个程序非常快,没有将数据发送到数据库,我每秒大约有10万行.当然,这个程序和数据库位于同一台物理计算机上.
现在,我每天获得的数据呈线性增长,INSERT的性能呈对数下降趋势.昨天的数据需要5个半小时才能插入,每秒大约插入400行.
我通过将具有不同配置的前100万行插入到空数据库中来获得一些基准数据,这几乎是我得到的:
MyISAM表:以每秒1500行的速度开始,在插入第100万行InnoDB表时,以每秒对数减少约700行:与MyISAM相同,每秒只有大约100行速度更快InnoDB,主要禁用所有索引table:以每秒2100行开始,每秒减少到1000行.InnoDB使用索引,文件系统安装了数据写回(ext3):与InnoDB相同,只是稍微但几乎不明显更快.
innodb_buffer_pool_size设置为1000MB
避免索引创建不是一种选择,但很明显它对性能有很大影响.但是,我需要更快的插入.如数据所示,随着数据库的增长,插入将花费更长的时间,因此我每天获得的数据越来越大,我需要在插入性能上有一个巨大的飞跃.如果我能够达到每秒10000次插入或更多,那将非常棒.
系统监视器告诉我我的主要资源消耗是磁盘I/O,插入时几乎达到100%.因此,我需要一种超快速的方式来插入数据.我的理论限制是SATA总线,但这仍然很遥远.内存使用量似乎没有那么高,大约20%(或MySQL没有正确使用内存)
要实现这一点,可以在几天内重新创建数据库,然后从阅读器应用程序进行热交换,可以更改操作系统和MySQL中的任何设置,如果需要可以添加内存.如有必要,甚至可以更改数据库结构.
所以我在这里真的很开心.有人知道什么可以帮助我吗?
编辑:我正在考虑在MEMORY表中插入新行,然后在真实表中执行SELECT INTO.希望它只会在插入所有行后更新并刷新索引.我会在星期一试试.以前有人试过这样的事吗?
小智 7
经过一整天的大量小事,我构建了一件巨大的东西.最重要的是,我将插入性能提高了大约8倍,达到每秒近10000条记录.
这是我做的事情:
重写加载程序.我说它是在C中,但它实际上是在C++中.使用mmap将字符串更改为char*,fstream,以及其他类似的东西,我的性能几乎翻了一番.(很多人仍然声称C++和C一样快,或者比C更快.我甚至不想在C#/ Java中尝试这个)
我找到了这个页面:http: //kevin.vanzonneveld.net/techblog/article/improve_mysql_insert_performance/ 这是一个很好的资源(我不隶属于他们),这几乎解释了我要尝试的一切,所有的各种结果.实际上,唯一可以超级插入性能的是使用LOAD DATA INFILE.调整我的表结构,所以我可以像这样插入几乎四倍!插入的表现.
我用LOAD DATA INFILE重写了无法执行的插入,使用ON DUPLICATE KEY UPDATE中的复杂表达式重写大量插入(每个插入命令几行),而不是为每一行执行SELECT/INSERT.这也提供了非常好的性能提升.这也需要对表结构进行一些修改.
重新创建已经超过20亿行的数据库时,创建表,这些表获取没有索引的LOAD DATA INFILE插入,并在完成后重新创建它们.我的所有基准测试表明,没有索引的插入时间加上创建它们的时间比插入带索引的表的时间要短.差异并不大,但却很明显(大约快了1.2倍).我认为B树也会以这种方式更好地平衡.
使用MyISAM.我以前的基准测试并不是那么有用,但是当使用LOAD DATA INFILE时,InnoDB每次都会丢失.在本地测试,我在MyISAM /无索引中获得大约16000条记录/秒,在MyISAM /索引中获得12000条记录/秒,在InnoDB /无索引中获得9000条记录/秒,在InnoDB /索引中获得大约7500条记录/秒.MySQL版本是5.1.47.
对于LOAD DATA INFILE的文件,在tmpfs挂载分区中创建它们.这也是一个巨大的性能提升,特别是因为您需要编写写入文件并将其刷新到磁盘,因此MySQL可以读取它.如果无法使用此tmpfs,则可以使用命名管道执行此操作.
获得的经验:当MySQL速度很慢时,你很可能通过改变你的代码来做更多的事情,而不是获得更强大的硬件.
祝你好运,谢谢大家的帮助.
6.5 小时内 200 万行?
您存储的数据集有多大?
我使用以下粗略计算得出一个有点有用的数字:
假设1单个蹩脚磁盘每秒吞咽35mb,那么您应该能够800 gb在那时写入 (35 * 6,5 * 3600) = ~框架。向后计算(800 GB / 2 mrows),得出平均行大小为400kb。
如果这些数字看起来正确,那么您需要增强硬件以提高速度。如果它们完全关闭,则可能存在其他问题。
另外,请查看ServerFault 上专用 MySQL 服务器的磁盘 I/O 比较,以了解测量 I/O 的方法。
以下是一些随机建议(以防您怀疑其他问题)
编辑
更正计算 (400kb)
| 归档时间: |
|
| 查看次数: |
7041 次 |
| 最近记录: |