【发布时间】:2011-07-04 08:47:22
【问题描述】:
我知道这个问题已经被问了一遍又一遍。但是,对于一个非常具体的场景,这是一个非常具体的问题。希望你能帮助我。
我运行一个日志数据库,大约有 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 行开始,到插入第 1 百万行时以对数方式减少到每秒约 700 行 InnoDB 表:与 MyISAM 相同,仅快 100 行/秒左右 在主表上禁用所有索引的 InnoDB:从每秒 2100 行开始,下降到每秒 1000 行。 InnoDB 带索引,文件系统挂载数据写回 (ext3):与 InnoDB 相同,只是速度稍快但几乎没有明显的加快。
innodb_buffer_pool_size 设置为 1000MB
避免创建索引不是一种选择,但很明显它对性能有很大影响。但是,我需要更快的插入。数据显示,随着数据库的增长,插入会花费更长的时间,所以随着我每天获取的数据越来越大,我需要在插入性能上实现巨大的飞跃。如果我能把它提高到每秒 10000 次或更多,那就太好了。
系统监视器告诉我,我的主要资源消耗是磁盘 I/O,插入时几乎达到 100%。因此,我需要一种超快速的方式来插入数据。我的理论极限是 SATA 总线的极限,但这还很遥远。内存使用率似乎没有那么高,大约 20%(或者 MySQL 没有正确使用内存)
为了实现这一点,可以在几天内重新创建数据库,然后从阅读器应用程序进行热交换,可以更改 OS 和 MySQL 中的任何设置,如果添加内存是可以接受的必需的。如有必要,甚至可以更改数据库结构。
所以我对这里的想法非常开放。有人知道什么可以帮助我吗?
编辑:我目前正在考虑在 MEMORY 表中插入新行,然后执行 SELECT INTO 实际表。希望它只会在插入所有行后更新和刷新一次索引。我会在星期一试试这个。有没有人尝试过这样的事情?
【问题讨论】:
标签: mysql database linux insert performance