草庐IT

mysql - 在 MySQL InnoDB 中替换为表非常慢

coder 2023-10-19 原文

使用 MySQL(确切地说是 MariaDB)。我有以下脚本,需要每隔一天运行一次以更新我的数据库,但速度慢得令人无法忍受。每个要更新的表都需要运行数小时。这是一个 shell 脚本:

CMD_MYSQL="${MYSQL_DIR}mysql  --local-infile=1 --default-character-set=utf8 --protocol=${MYSQL_PROTOCOL} --port=${MYSQL_PORT} --user=${MYSQL_USER} --pass=${MYSQL_PASS} --host=${MYSQL_HOST} --database=${MYSQL_DB}"

### Update MySQL Data ###
## table name are lowercase
tablename=`echo $FILE | tr "[[:upper:]]" "[[:lower:]]"`
echo "Uploading ($FILE) to ($MYSQL_DB.$tablename) with REPLACE option..."
## let's try with the REPLACE OPTION
$CMD_MYSQL --execute="LOAD DATA LOCAL INFILE '$FILE.txt' REPLACE INTO TABLE $tablename CHARACTER SET utf8 FIELDS TERMINATED BY '|' IGNORE 1 LINES;"
## we need to erase the records, NOT updated today
echo "erasing old records from ($tablename)..."
$CMD_MYSQL --execute="DELETE FROM $tablename WHERE datediff(TimeStamp, now()) < 0;"

您可以安全地忽略文件中其他地方设置的一些变量。 $FILE 通常是由 | 分隔的 txt 文件。每行代表一条记录,示例:

AirportID|AirportCode|AirportName|Latitude|Longitude|MainCityID|CountryCode
6024358|DME|Moscow, Russia (DME-Domodedovo Intl.)|55.414495|37.899907|2395|RU
6024360|DMM|Dammam, Saudi Arabia (DMM-King Fahd Intl.)|26.468075|49.796824|180543|SA

该脚本在现有数据库上运行,其中包含旧记录。然后它检查其最后更新日期,并执行 REPLACE INTO,但对于 100MB 的 txt 文件通常需要 8 个小时。

如何显着提高速度?

最佳答案

此问题会影响所有版本的 InnoDB (4.1+)。在 InnoDB 中替换重复项太慢了。这是 MyISAM 优越的地方。 MyISAM 用了 0.05 秒。

原因是InnoDB中的duplicate key错误处理依赖于undo log和statement rollback: 1.锁定记录。 2. 写入update_undo log 删除标记记录。 3. 写入插入记录的insert_undo log。 4. 尝试插入新记录。 5.注意重复。 6.回滚步骤3和步骤2写入的undo log。

这是 MySQL 中的一个问题,截至 2019 年 9 月尚未在任何版本中修复: https://bugs.mysql.com/bug.php?id=71507

他们计划在第 2 步检测重复项。这将避免在这种情况下发生任何回滚。

这里有两个建议:

  1. 如果适用,使用 MyISAM
  2. 使用诸如 INSERT INTO ... ON DUPLICATE KEY UPDATE ... 之类的查询

关于mysql - 在 MySQL InnoDB 中替换为表非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21485394/

有关mysql - 在 MySQL InnoDB 中替换为表非常慢的更多相关文章

  1. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  2. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  3. 使用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

  4. ruby - Ruby gsub 替换中的行为不一致? - 2

    两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

  5. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  6. ruby-on-rails - 在这种情况下我如何模拟一个对象?没有明显的方法可以用模拟替换对象 - 2

    假设我在Store的模型中有这个非常简单的方法:defgeocode_addressloc=Store.geocode(address)self.lat=loc.latself.lng=loc.lngend如果我想编写一些不受地理编码服务影响的测试脚本,这些脚本可能已关闭、有限制或取决于我的互联网连接,我该如何模拟地理编码服务?如果我可以将地理编码对象传递到该方法中,那将很容易,但我不知道在这种情况下该怎么做。谢谢!特里斯坦 最佳答案 使用内置模拟和stub的rspecs,你可以做这样的事情:setupdo@subject=MyCl

  7. ruby - 如何搜索、递增和替换 Ruby 字符串中的整数子字符串? - 2

    我有很多这样的文档:foo_1foo_2foo_3bar_1foo_4...我想通过获取foo_[X]的所有实例并将它们中的每一个替换为foo_[X+1]来转换它们。在这个例子中:foo_2foo_3foo_4bar_1foo_5...我可以用gsub和一个block来做到这一点吗?如果不是,最干净的方法是什么?我真的在寻找一个优雅的解决方案,因为我总是可以暴力破解它,但我觉得有一些正则表达式技巧值得学习。 最佳答案 我(完全)不懂Ruby,但类似这样的东西应该可以工作:"foo_1foo_2".gsub(/(foo_)(\d+)/

  8. ruby - 改变替换的大小写 - 2

    我有以下内容:text.gsub(/(lower)(upper)/,'\1\2')我可以将\2替换为大写吗?类似于:sed-e's/\(abc\)/\U\1/'这在Ruby中可行吗? 最佳答案 查看gsub文档:str.gsub(模式){|匹配|block}→new_str在block形式中,当前匹配字符串作为参数传入,$1、$2、$`、$&、$'等变量将被适当设置。block返回的值将替换为每次调用的匹配项。"alowerupperb".gsub(/(lower)(upper)/){|s|$1+""+$2.upcase}

  9. 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

  10. ruby-on-rails - 在 rails 中分配/替换参数哈希 - 2

    我在RailsController操作中有下面的代码序列。在IF之前,params包含请求参数,正如预期的那样。在它之后,params为零。谁能解释一下这里发生了什么?iffalseparams={:user=>{:name=>"user",:comment=>'comment'}}end谢谢。 最佳答案 params其中包含请求参数实际上是一个方法调用,它返回包含参数的散列。你的params=行正在分配给一个名为params的局部变量.iffalse之后block,Ruby已经看到了本地params变量,所以当你引用params时

随机推荐