提高 SQL 'Update' 函数的速度 - 插入/删除?

Improving Speed of SQL 'Update' function - break into Insert/ Delete?

我是 运行 一个 ETL 进程并将数据流式传输到 MySQL table。

现在它是通过网络连接(相当快的)编写的——所以这可能是一个瓶颈。

总之,这是一个基本的插入/更新功能。它是作为主键/索引的 ID 列表....然后是一些属性。

如果找到新的 ID,则插入,否则,更新......你明白了。

目前,基于 ID(索引)执行 "update, else insert" 函数每秒需要 13 行(这看起来很糟糕,对吧?)。这是将 1000 行与 250k 条记录的数据库进行比较,以了解上下文。

当执行 "pure" insert everything 方法时,为了比较,已经将过程加速到 26 行/秒。

纯 "insert" 方法的问题是我可以同时拥有 20 个并行连接 "inserting" ...(网络主机允许的最大值为 20)...而任何 "update" 函数不能有任何相似之处 运行.

因此 26 x 20 = 520 r/s。远远大于 13 r/s,特别是如果我可以装配一些东西,允许更多的数据并行推送。

我的问题是...考虑到插入与更新的巨大好处,有没有办法复制 'update' 功能(我只希望给定 ID 的最新插入保留下来)。 ...通过大量插入,然后 运行 事后删除函数,删除不是 'newest' ?

的重复 ID

这是容易实现的东西,还是经常出现的东西?

我还能做些什么来确保更新过程更快?我知道摆脱 ETL 工具和数据库之间的 'web connection' 是一个开始,但还有什么?这似乎是一个相当普遍的问题。

最终有 20 列,最多可能是 varchar(50) ...我应该每秒处理超过 13 行吗?

您的问题有多种可能 'answers'。

13/秒 -- 可以完成很多...

INSERT ... ON DUPLICATE KEY UPDATE ... ('IODKU') 通常是 "update, else insert" 的最佳方式(除非我不明白你的意思)。

批量插入比一次插入一行要快得多。最佳是大约 100 行,可提供 10 倍的加速。 IODKU 也可以(通常)进行批处理;请参阅 VALUES() 伪函数。

BEGIN;...大量写入...COMMIT; 显着减少事务开销。

使用 "staging" table 来收集更新可以带来很大的好处。 My blog discussing that. 这也涵盖批次 "normalization".

动态构建汇总表会干扰高速数据摄取。 Another blog covers Summary tables.

规范化可用于重复数据删除,从而减少磁盘占用空间。这对于减少数据仓库中 'Fact' table 的 I/O 可能很重要。 (我指的是你的 20 x VARCHAR(50)。)

RAID 条带化是一种硬件帮助。

RAID 控制器上的 Batter-Backed-Write-Cache 使写入看起来是瞬时的。

SSD 加速 I/O。

如果您提供更具体的信息(SHOW CREATE TABLE、SQL 等),我可以更具体。

在 DBMS 中执行,并将其包装在事务中。

说明:

  1. 以尽可能最快的方式将数据加载到 MySQL 中的临时 table。批量加载,插入,做任何工作。看看"load data infile".

  2. 将临时 table 外联到目标 table,并插入目标 table 的 PK 列为 NULL 的那些行。

  3. 将临时 table 外联到目标 table,并更新目标 table 的 PK 列不为空的那些行。

将步骤 2 和 3 包装在 begin/commit(或事务的 [start transaction]/commit 对中。默认行为可能是自动提交,这意味着您将在之后做大量的数据库工作every insert/update。合理使用交易,每个区块只做一次工作。