r—如何避免将大文件并行加载到mysql时出现超时错误

xienkqul  于 2021-06-21  发布在  Mysql
关注(0)|答案(1)|浏览(358)

我必须循环通过几个数据集分别存储在单个csv文件-约1500个文件。每个文件代表一天的活动量,每个文件中的数据量从基本上没有变化到很大。
我的过程是将数据加载到r中,进行预处理和清理,然后插入到本地mysql表中。作为一个单循环运行,它可以很好地工作。
为了提高加载速度,我尝试将循环移动到一个并行进程中,在这个进程中,我让几个工作人员预处理单独的文件,然后每个工作人员将它们加载到数据库中。
当一些文件很大,并且dbwritetable调用需要一些时间来处理时,我遇到了一个错误。这似乎在表上设置了锁,不允许其他进程完成写入,从而导致超时错误。
我对mysql还相当陌生,我隐约知道我可以在数据库级别更改mysql超时时间(我相信使用conf文件)。这是最好的/唯一的解决方案吗?我更喜欢将所有控件保持在r级别,这样我就可以更轻松地在不同的机器上运行此代码。我想知道是否有另一种方法来保持进程在队列中,并在表可用时按顺序写入负载。
更新:
我以为这是一个关于如何处理超时的简单问题,但听起来需要更多的信息。这里有一个例子——并不复杂。

Bluetooth.loadloop <- foreach(i=jump:LoopLength, .inorder=TRUE) %dopar% {

    Start.Time <- Sys.time()
    x <- filenames[i]  

    if(!length(readLines(x))) {
      Stats <- data.frame(
        i=i, 
        time=difftime(Sys.time(),Start.Time,units='secs'),
        DataList= 0 )

      source("/Shared_Functions/MYSQL_LOGIN.r" )
      invisible(dbWriteTable(con, name="RawData_Loadloop_Stats_Bluetooth",value=Stats, append=TRUE, row.names=FALSE))
      dbDisconnect(con)
      print( "Zero length");

      return("Zero length")
    } else {

      ### Loads Data from CSV
      print(paste(i,"Start"))
      datalist <-readLines(x,encoding="UTF-8")
      filelocation <- (paste(i,x))
      datalist.length <- length(datalist)
      print(datalist.length)

      ### Proceses the individual fields 
      deviceID <- v1 <- gsub("([0-9]+),.*", "\\1", datalist)
      Time <- v2 <- gsub("[0-9]+,([0-9]+),.*", "\\1", datalist)
      Label <- v3 <- gsub("^[0-9]+,[0-9]+,(.*),([a-zA-Z0-9:]+),([^,]+)$", "\\1", datalist)
      MacAddress <- v4 <- gsub("^[0-9]+,[0-9]+,(.*),([a-zA-Z0-9:]+),([^,]+)$", "\\2", datalist)
      Strength <- v5 <- gsub("^[0-9]+,[0-9]+,(.*),([a-zA-Z0-9:]+),([^,]+)$", "\\3", datalist)

      Label <- BlueToothFilterRules(Label)
      Encoding(Label) <- 'UTF-8'
      BlueToothTable <- data.frame(i=i, DeviceID = deviceID, Time= Time, Label= Label, Mac = MacAddress, Strength= Strength, stringsAsFactors = FALSE)

      Stats <- data.frame(
        i=i, 
        time=difftime(Sys.time(),Start.Time,units='secs'),
        DataList= datalist.length
      )

      ### Writes to the Database
      source("/Shared_Functions/MYSQL_LOGIN.r" )
      dbSendQuery(con, 'set character set "utf8"')
      invisible(dbWriteTable(con, name="RawData_Events_Bluetooth",value=BlueToothTable, append=TRUE, row.names=FALSE))
      invisible(dbWriteTable(con, name="RawData_Loadloop_Stats_Bluetooth",value=Stats, append=TRUE, row.names=FALSE))
      dbDisconnect(con)
      print(paste(i,"END"));

      return("Finished")
    }
  }

所以,当这是并行运行,如我所说,它在写瓶颈,导致超时。
我不知道该如何处理用户3666197所说的话,否则最好是为这些错误做好准备,并在处理这些错误时精心设计。
将readin和write分开也不是一个现实的选择,因为结果对象太大,无法很好地处理。
我知道并行运行这个程序将提供有限的改进,因为存在瓶颈,但是它将减少总的处理时间,因为它允许其他工作人员在加载所有数据时加载并处理原始数据。
所以我最初的问题仍然是-如何最好地处理mysql写队列,以便并行运行时不会产生超时错误?
谢谢您

c2e8gylq

c2e8gylq1#

在一个mcve公式化的问题中没有代码,让我们在没有任何代码的答案中继续。
虽然所有适当的数学公式都在本文的结尾部分,但一个可读的故事可能是一个更好的方法,以获得坚实的掌握主要 TimeOut 问题根本原因:

使用并行语法构造函数?在许多地方和许多时尚中,语法上是可能的,但是。。。

这里(总是)的重点是,这是否有意义。要回答这个问题,就必须知道使用它的所有成本的总和。
成本是,因为我们的核心动机是处理加速,我们需要及时支付管理费用,然后才能享受使用“加速”结果。

我们来举个例子——科德角机场的故事:

一个城市的市长决定修建一条新的高速公路,以便让受欢迎的市民能够更快地乘车到达科德角一角的机场。
这听起来很符合逻辑,也很棒。因此,他们开始投资,已经支付了数百名房东购买了所有新的地块(购买该地产以修建新道路),采石工人挖掘所有需要的岩石,碾磨工人将其磨成合适大小的石头、沙子、水泥和沥青,所有这些都是公路所需,推土机操作员将道路岩石铺设在地基上,随着公路建设的推进,混凝土供应商负责及时搅拌和交付水泥等。
几个月或几年后(取决于当地经济、承包商的表现、城市预算及其与机场的距离。。。当然),高速公路已经完工,开幕式也举行了。
此时此刻有两件事是确定无疑的——成本——建造这样一条公路花了多少钱,再加上——等待时间——第一辆车从城市开到机场要花多长时间。
最后一件事是——实现的净加速比——那么这条新的100车道宽的高速公路最终有多快,如果与旧的和使用了很久的可爱的乡村公路相比的话。

结果如何?

首先是已知的性能基线:
a、b、c、d车。。。x、 大约几个月(几年)前,y、z都开始前往机场,以每小时约40英里的速度舒适地行驶,而且都在大约一个小时内,一个接一个地,以纯粹的速度到达机场 [SERIAL] 态度。没有什么性感,但一个坚实的,可重复的结果,因为下一次,这些将享受几乎相同的结果再次。
和新的平行车手相比:
汽车a1,a2,a3。。。a100,b101。。。b200。。。z2600都有相同的目标,以尽可能快的速度到达机场,但要等几个月(几年)才能建成新的高速公路(一个明显的处理设置延迟),接下来花了大约几分钟的时间在这条新高速公路上享受超快的旅程,像德国一样没有速度限制,所以200英里?时速300英里?没问题。
在此之前,在100条平行车道宽的新高速公路上以300英里/小时的速度驾驶汽车的惊险3分钟超快体验已经到达海岸线,接下来,每辆汽车都必须排队等待下一艘渡轮的到来(容量仅为30辆左右,还可服务于所有传统的当地交通)。
假设一条轮渡线有大约40分钟的rtt服务(往返时间——装载前30辆汽车,前往科德角,卸载汽车,然后装载那些返回的汽车,从科德角返回大陆港口),游戏就快结束了。
结果:
-整个a:z组 has made the task in T0 +01:00:00 时间
-小于等于30个平行车手的第一个子集 has made the same in T0 +8760:23:00 -小于等于30个平行车手的下一个子集 has made the same in T0 +8760:43:00 -小于等于30个平行车手的下一个子集 has made the same in T0 +8761:03:00 -小于等于30个平行车手的下一个子集 has made the same in T0 +8761:23:00 -小于等于30个平行车手的下一个子集 has made the same in T0 +8761:43:00 -小于等于30个平行车手的下一个子集 has made the same in T0 +8762:03:00 ...
-<=30个平行车手的最后一个子集 has made the same in T0 +8788:43:00 所有这些条件如下:
-在这大约29小时内,没有任何当地交通出现
-第一艘渡轮空无一人,准备在第一批30辆汽车抵达港口后立即开始装货
-从未出现过渡轮服务中断或时间表服务不规范的情况

故事的结尾:

在现实世界中不可能有更好的结果,在资源受限的并行计算图形执行中也不可能有更好的结果。

结语:

只有一个“公正”- [CONCURRENT] 否则为真的元素- [PARALLEL] 安装可能如此昂贵-幸运的是,所有约x.000.000.000美元和约8760多个小时的费用神奇地“免费”,
但是
真正的计算机从来没有这么宽容过
而且代码总是会支付他们所有的费用,总是(设计方面,代码执行方面),所以适当的工程努力和适当的设计谨慎总是到位的,不会得到任何回报 << 1 加速惊喜。

相关问题