【问题标题】:SQL - faster way to UPDATE column entriesSQL - 更新列条目的更快方法
【发布时间】:2015-06-21 04:28:26
【问题描述】:

我有一个类似下面的 SQL 表:

id | text | other_columns...
----------------------------
 0 |  a   |      ...
 1 |  b   |      ...
 2 |  c   |      ...

我需要对text 列中的值应用一些复杂的操作,然后用新值更新这些字段。

 // Get all the current values.
 entries = SELECT id,text FROM foo_table;

 // Apply some complex operation to the text values (this part is Python, not SQL).
 foreach entry in entries
     entry.text = f(entry.text)

 // Update the text fields (1 UPDATE per entry).
 foreach entry in entries
     UPDATE foo_table SET text=entry.text WHERE id=entry.id;

这会产生一个像这样的表格,其中包含更新的文本值:

id | text | other_columns...
----------------------------
 0 |  x   |      ...
 1 |  y   |      ...
 2 |  z   |      ...

每次更新大约需要 1 毫秒,我有大约 500 万个条目,这会导致大约 8 分钟的执行时间。我正在批处理 SQL 命令(一次 1000 个),但这似乎仍然很慢/效率低。

有没有更好(更快)的方法来做到这一点?谢谢。

【问题讨论】:

  • 复杂的操作是什么(如果你能告诉我们)?也许它可以在 SQL 中完成,这肯定会加快速度。
  • 你能提供显示索引的数据创建stmt
  • @PabloGonzálezAlba “复杂操作”正在执行一系列自定义字符串标记化/替换和引用外部数据源。不幸的是,它不能在 SQL 中完成(即使可以完成,在 SQL 中重新实现也非常昂贵)。
  • @DrewPierce 不确定我是否理解您的要求。你是说数据类型吗? idint/primary keytextvarchar。表中有许多具有不同数据类型的附加列。
  • @smg 好的。您应该确保id 字段有一个索引,您可以查看this answer 以一次性发送所有语句,看看它是否有帮助。我想不出任何其他改进。

标签: mysql database


【解决方案1】:

通过 OUTFILE 导出导出到 2 列的 txtfile。

SELECT id, theText
  INTO OUTFILE '/path/to/file.csv'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM myTable

让 Py 做一个输入。

可以有 2 列或 3 列。假设 3 用于调试目的。

现在你已经出局了。将带有 INFILE 的 mysql 带回带有 id,newText 的工作表中。

    LOAD DATA INFILE 'data.txt' INTO TABLE worktable
  FIELDS TERMINATED BY ',' ENCLOSED BY '"'
      LINES TERMINATED BY '\r\n';

https://dev.mysql.com/doc/refman/5.1/en/load-data.html

请注意,要导入的数据可以有 row1 和列名。当然,可以跳过第 1 行进行数据导入,但通过命名列,您只能引入某些列。在您的情况下,3 列中有 2 列。

导入后在 worktable.id 上添加索引。

更新会很快。

UPDATE myTable
JOIN worktable
ON worktable.id=myTable.id
SET myTable.text=worktable.newText

这整个事情可以在一个封闭的 bash 脚本中发生。如果不知道怎么问。

【讨论】:

  • 是的,您可以在 SQL 中创建一个将整个表作为参数的存储过程,然后使用存储过程的表更新目标表。这可以让您将整个表拉入您的 python 代码,进行所有更改,然后一次更新。
  • 我知道,我是说让 Python 调用存储过程并将表作为参数传入。
  • @DiscipleMichael 在代码中展示了这一点。我相信 OP 也希望看到你的模型。您的答案下方有一个答案槽,用于显示详细信息。
【解决方案2】:

我可能在这里遗漏了一些重要的东西,但你为什么不能这样做

Update foo_table;
Set foo_table.text = f(foo_table.text)

【讨论】:

  • 对,但如果他实际上是在 SQL 代码中调用函数 f(),他也应该能够做到这一点。也许,为了简洁起见,他只是简化了对函数的调用?
  • 我不这么认为。他被调查了
  • 我正在使用f 将操作从这个问题中抽象出来。 f 实际上是一些在 Python 中应用的复杂函数。
【解决方案3】:

你可以使用 UDF,但你必须用 C 重写你的函数。

【讨论】:

    猜你喜欢
    • 2021-11-02
    • 2012-01-23
    • 2021-04-17
    • 1970-01-01
    • 2023-04-07
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多