【问题标题】:How to split my inserts into smaller pieces?如何将我的插入物分割成更小的部分?
【发布时间】:2013-10-29 07:37:46
【问题描述】:

这是我的导入脚本。我有大约 400 000 条记录。并且在插入记录期间我的连接关闭。如何将其拆分为更小的部分?

  def extract_to_database(collection)
    tmp       = []
    type      = K
    inserts = []

    collection.each_with_index do |line, i|
      _type    = line.strip
      _changed = TYPES.include? _type

      if _changed && i > 0
        case type
        when K then @k << tmp
        when F then @f << tmp
        when FB then @f << tmp
        when I, D
          pharmaceutic = Pharmaceutic.find_by pzn: tmp[PZN]
          if pharmaceutic
            inserts.push "(#{pharmaceutic.id}, '#{tmp[UNIT]}', '#{tmp[DOSE]}')"
          end
        end

        tmp  = []
        type = _type
      end

      tmp << clean(line)
    end
    sql = "INSERT INTO pharmaceutic_dosages (`pharmaceutic_id`, `unit`, `dose`) VALUES #{inserts.join(", ")}"
    CONN.execute sql
  end

【问题讨论】:

  • 您面临的实际问题是什么?
  • 这可能是一个 X,Y 问题,您正在沿着路径 X 寻找解决方案,而实际上您正在尝试解决可能具有完全不同、更好和/或更多的 Y有效的解决方案,如果您想告诉我们更多有关数据和数据库的信息。关闭自动索引可以加速更新/插入,关闭提交并在 n 条记录之后定期提交也可以。你说你的连接正在关闭,但不要告诉我们是否产生了错误,应该有,但不要给我们实际的文本。
  • 另外,在您准备好使用之前不要打开您的数据库连接。您没有显示连接的时间/地点,但打开它被认为是不好的形式,让它挂起一段不确定的时间,然后最终使用它。打开连接使用服务器上的资源,因此当您加载数据时,打开连接,立即执行您需要执行的操作,然后断开连接。

标签: mysql ruby-on-rails ruby import


【解决方案1】:

您的问题中缺少很多必要的信息,特别是您正在使用的 DBM、您的超时值设置为什么、您在代码中打开数据库连接的位置、实际需要多长时间处理 400,000 条记录等的代码。所有这些都会影响您工作的成败。

这段代码引起了我的注意:

sql = "INSERT INTO pharmaceutic_dosages (`pharmaceutic_id`, `unit`, `dose`) VALUES #{inserts.join(", ")}"
CONN.execute sql

您在哪里打开与数据库的连接?为什么你打开它然后不立即使用它?数据库配置为在一段时间后关闭未使用的连接,因为连接会占用内存和 CPU 时间。连接后,发送更新/删除/插入,无论如何,然后关闭它。如果您经常连接/关闭,您只需要一个持久的连接,这也可能是 DBM/服务器的大量 CPU 消耗。

在计算时不要打开然后保持连接,而是等到数据准备好后再打开它,然后打开它并立即发送。我不知道您使用的是什么驱动程序或 DBM,因此请考虑以下伪代码:

sql = "INSERT INTO pharmaceutic_dosages (`pharmaceutic_id`, `unit`, `dose`) VALUES #{inserts.join(", ")}"    
CONN = connect_to_database(...)
CONN.execute sql
CONN.close

这样做,我怀疑你会看到超时错误。

【讨论】:

    【解决方案2】:

    如果连接在插入记录时关闭,为什么不让脚本将 SQL 语句写入文件,然后针对数据库运行这些插入?

    所以:

    1. 按照上述脚本生成 SQL 语句。
    2. 将它们写入文件(本地或 S3 上)。
    3. 复制该文件的内容并在数据库控制台中运行。

    似乎这样也可以防止 OOM 错误。

    【讨论】:

      【解决方案3】:

      前段时间我也遇到过同样的问题。我找到的最佳解决方案是使用 resque 的后台作业。见this答案。

      我还使用resque-status 向用户显示 WIP。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-12-25
        • 2018-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多