草庐IT

php - SQL 插入速度的变化

coder 2023-10-03 原文

我正在处理的脚本旨在更新一个数据库表,该表记录了使用国家和所有 IP 地址(或几乎所有 IP 地址)的状态。目前我保持简单,只从 5 个 RIR(区域互联网注册机构)获取数据并将其保存到我的数据库中。

最初速度是不切实际的,但通过减少日志中的信息量并将 SQL 插入分组为 1000 组并使用单个查询,速度得到了显着改善。但是,现在运行脚本时,SQL 插入的速度变化很大,我想知道是否有人知道为什么。

这是我记录的一些速度。在测试中,我将执行 PHP 脚本迭代所花费的时间和应用 sql 语句所花费的时间分开,我没有将 PHP 时间包括在下面的列表中,因为影响可以忽略不计;即使是最大的数据 block 也不超过 1 秒。

测试速度(插入的数据行数始终保持不变)

测试 1 SQL总执行时间:33秒

测试 2 SQL总执行时间:72秒

测试 3 SQL总执行时间:78秒

其他测试继续在 ~30 秒和 ~80 秒之间波动。

我有两个问题:

1) 我应该接受这些差异作为世界的方式,还是有理由接受它们?

2) 我对将 ~185000 行插入集中到一个查询中感到紧张。有什么理由我应该避免对这些插入使用一个查询吗?我以前从未处理过一次保存这么多数据。

谢谢

__

数据库表如下。

Sorage 引擎 - InnoDB

列:

id - 整数,主键

注册表 - varchar(7)

代码 - varchar(2)

类型 - varchar(4)

开始 - varchar(15)

值 - 整数

日期 - 日期时间

状态 - varchar(10)

最佳答案

1) Should I accept these disparities as the way of the world, or is there a reason for them?

速度的变化可能是由于使用磁盘 IO 的竞争进程 - 所以等待资源。如果这是生产服务器而不是单独的测试服务器,那么肯定有一些其他进程正在请求访问磁盘。

2) I felt nervous about lumping the ~185000 row inserts into one query. Is there any reason I should avoid using one query for these inserts? I've not worked with this amount of data being saved at one time before.

您还应该将插入分成 X 个插入组,并将每个组作为一个事务插入。

除了实验之外,很难通过其他方式确定 X 的值。

将插入分组到事务中可确保仅在每个事务之后而不是在每次(自动提交)插入之后将数据写入(提交)到磁盘。

这对磁盘 IO 有很好的影响,如果你将许多插入分组到一个事务中,它会对可用内存产生不良影响。如果未提交的数据量对于当前内存来说太大,DBMS 将开始将数据写入内部日志(在磁盘上)。

所以 X 取决于插入的数量、与每个插入相关的数据量、允许的内存/用户/ session 参数。还有很多其他的东西。


percona 提供了一些很棒的(免费)工具.它们帮助您监控数据库事件。

你也可以看看vmstat watch -n .5 'vmstat'

查看生产环境的事件写入磁盘的数据量和变化。

启动您的脚本并等待,直到您注意到写入磁盘的字节数增加。如果写 step up 几乎是一个常数值(高于正常生产使用),那么它就是颠簸和交换,如果它是有节奏的,那么它只是为提交而写。

关于php - SQL 插入速度的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12797368/

有关php - SQL 插入速度的变化的更多相关文章

  1. ruby-on-rails - 启用 Rack::Deflater 时 ETag 发生变化 - 2

    在启用Rack::Deflater来gzip我的响应主体时偶然发现了一些奇怪的东西。也许我遗漏了一些东西,但启用此功能后,响应被压缩,但是资源的ETag在每个请求上都会发生变化。这会强制应用程序每次都响应,而不是发送304。这在没有启用Rack::Deflater的情况下有效,我已经验证页面源没有改变。我正在运行一个使用thin作为Web服务器的Rails应用程序。Gemfile.lockhttps://gist.github.com/2510816有没有什么方法可以让我从Rack中间件获得更多的输出,这样我就可以看到发生了什么?提前致谢。 最佳答案

  2. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  3. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

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

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

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

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

  6. sql - 在 Rails Console for PostgreSQL 的表中显示数据 - 2

    我找到了这样的东西:Rails:Howtolistdatabasetables/objectsusingtheRailsconsole?这一行没问题:ActiveRecord::Base.connection.tables并返回所有表但是ActiveRecord::Base.connection.table_structure("users")产生错误:ActiveRecord::Base.connection.table_structure("projects")我认为table_structure不是Postgres方法。如何列出Postgres数据库的Rails控制台中表中的所有

  7. ruby-on-rails - 在方法调用中插入 Ruby? - 2

    在我的用户模型中,我有一堆属性,例如is_foos_admin和is_bars_admin,它们决定允许用户编辑哪些类型的记录。我想干掉我的编辑链接,目前看起来像这样:'edit'ifcurrent_user.is_foos_admin?%>...'edit'ifcurrent_user.is_bars_admin?%>我想做一个帮助程序,让我传入一个foo或bar并返回一个链接来编辑它,就像这样:助手可能看起来像这样(这不起作用):defedit_link_for(thing)ifcurrent_user.is_things_admin?link_to'Edit',edit_poly

  8. ruby-on-rails - ruby 中两个哈希之间的变化 - 2

    我有两个具有以下格式的哈希mydetails[x['Id']]=x['Amount']这将包含如下数据hash1={"A"=>"0","B"=>"1","C"=>"0","F"=>"1"}hash2={"A"=>"0","B"=>"3","C"=>"0","E"=>"1"}我期待这样的输出:Differencesinhash:"B,F,E"非常感谢任何帮助。 最佳答案 这个解决方案可能更容易理解:(hash1.keys|hash2.keys).select{|key|hash1[key]!=hash2[key]}Array#|返回2

  9. ruby - 防止SQL注入(inject)/好的Ruby方法 - 2

    Ruby中防止SQL注入(inject)的好方法是什么? 最佳答案 直接使用ruby?使用准备好的语句:require'mysql'db=Mysql.new('localhost','user','password','database')statement=db.prepare"SELECT*FROMtableWHEREfield=?"statement.execute'value'statement.fetchstatement.close 关于ruby-防止SQL注入(inject

  10. Ruby 将对象插入现有的已排序对象数组 - 2

    我有以下现有的Dog对象数组,它们按age属性排序:classDogattr_accessor:agedefinitialize(age)@age=ageendenddogs=[Dog.new(1),Dog.new(4),Dog.new(10)]我现在想插入一条新的狗记录,并将它放在数组中的正确位置。假设我想插入这个对象:another_dog=Dog.new(8)我想把它插入到数组中,让它成为数组中的第三项。这是一个人为的示例,旨在演示我特别想如何将一个项目插入到现有的有序数组中。我意识到我可以创建一个全新的数组并重新对所有对象进行排序,但这不是我的目标。谢谢!

随机推荐