草庐IT

mysql - 特定的MySQL批量插入性能调优

coder 2023-06-17 原文

我知道这个问题已经被一遍又一遍地问了。但是,对于非常特定的情况,这是一个非常特定的问题。希望你能帮助我。

我运行一个约有10个表的日志数据库。存储实际日志条目的主表有大约30个字段,其中5个是可搜索的。我要说的是,数据库的大小最近有所增加,因为我们在该表中达到了2亿个条目。其他表存储公共(public)数据,其中最大的一个有4个字段,所有字段均可搜索,几乎有100万个条目。所有其他表均包含少于10万条记录。

嵌件有尖刺。我每天凌晨2点从前一天的日志(格式很差)的csv文件中获取日志,直到凌晨8点,我才将它们(大约20个文件,每行10万行)插入到数据库中。然后,在工作日中,我得到的选择很少(也许一天大约有1000个)。然后冲洗并重复。

SELECT查询非常简单,因为它们主要由一个或两个联接以及一个或两个GROUP BY语句组成。搜索该数据库的人员需要立即获得结果,因此我在主表中有5个多列索引,这些索引可以帮助我进行精确的搜索,并且目前SELECT性能非常好。到目前为止,没有任何查询花费超过0.1秒的时间。有一些报告,但是这些报告大约需要10秒钟才能生成,这是可以接受的。

当前,我编写了一个C程序来读取CSV文件中的数据,对其进行清理,然后按每个INSERT查询以1000行的批数进行插入。这些INSERT并不完全是愚蠢的,因为我需要获取公共(public)数据,查看它是否已经在其他表上,如果不是,则将其插入,如果是,则对其进行缓存。它还以每秒插入多少条记录的形式提供了性能数据。这个程序非常快,并且没有将数据发送到数据库中,我每秒获得约10万行。当然,该程序和数据库位于同一台物理计算机上。

现在,我每天获取的数据呈线性增长,而INSERT的性能呈对数下降。昨天的数据花了5个半小时才能插入,每秒插入大约400行。

通过将具有不同配置的前一百万行插入一个空数据库中,我得到了一些基准数据,这几乎就是我得到的:

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中的任何设置,可以根据需要添加内存。如有必要,甚至可以更改数据库结构。

所以我真的很愿意在这里提出想法。有人知道有什么可以帮助我的吗?

编辑:我目前正在考虑将新的行插入到内存表中,然后在实际表中执行SELECT INTO。希望它仅在插入所有行后更新和刷新索引一次。我星期一试试。有人尝试过这样的东西吗?

最佳答案

6,5小时内有200万行?
您存储的数据集有多大?

我使用下面的信封计算得出一个有用的数字:
假设ozt_code单个cr脚的磁盘每秒吞下1 mb,那么您应该能够在该时间范围内写入(35 * 6,5 * 3600)=〜35。向后计算(800 gb/2行),得出的平均行大小为800 gb kb。

如果这些数字看似正确,则需要增强硬件以提高速度。如果它们完全关闭,则可能还有其他问题。

另外,请查看ServerFault上的comparisons of disk i/o for a dedicated MySQL server,以了解一种测量I/O的方法。

以下是一些随机建议(以防您怀疑其他问题)

  • 确保在加载过程
  • 中消除了所有逐行操作
  • 如果最终存储了大多数csv数据,请考虑将bulk loading放入中间表中,并使用基于集合的处理来处理数据库中的数据。
  • 如果大多数数据被丢弃,请考虑将引用表移至数据库外/将其缓存在数据库之外,以便能够过滤C代码中的CSV数据
  • MySQL没有散列连接,但依赖于索引循环。确保其他表具有适当的索引
  • 尝试对数据库外部的数据进行预排序,以匹配流程中使用的其他表的索引(以增加相关数据不会从缓存中清除的可能性)
  • 阅读partitioning,看看是否可以用智能分区方案代替维护所有这些索引来替换某些索引。

  • 编辑
    更正的计算(400kb)

    关于mysql - 特定的MySQL批量插入性能调优,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5118595/

    有关mysql - 特定的MySQL批量插入性能调优的更多相关文章

    1. 使用canal同步MySQL数据到ES - 2

      文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

    2. Ruby - 如何在读取文件时跳过/忽略特定行? - 2

      在读取/解析文件(使用Ruby)时忽略某些行的最佳方法是什么?我正在尝试仅解析Cucumber.feature文件中的场景,并希望跳过不以Scenario/Given/When/Then/And/But开头的行。下面的代码有效,但它很荒谬,所以我正在寻找一个聪明的解决方案:)File.open(file).each_linedo|line|line.chomp!nextifline.empty?nextifline.include?"#"nextifline.include?"Feature"nextifline.include?"Inorder"nextifline.include?

    3. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

      我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

    4. ruby - 如何在 Ruby 字符串中插入项目符号字符? - 2

      我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195

    5. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

      我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

    6. Ruby 的数字方法性能 - 2

      我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

    7. ruby - Ruby 性能中的计时器 - 2

      我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

    8. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

      我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

    9. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

      如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

    10. ruby - 在 ruby​​ 中使用自动创建插入数组 - 2

      我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?

    随机推荐