【问题标题】:MySQL INSERT INTO SELECT very slowMySQL INSERT INTO SELECT 非常慢
【发布时间】:2012-03-11 03:11:10
【问题描述】:

我刚刚创建了一个空表document_test,它是document 表的副本。然后我将一个新的列主机添加到document_test 并从document 复制所有其他内容。语句是这样的:

INSERT INTO document_test (id,col1,col2,col3,col4) SELECT * from document;

document 表包含大约 550 万行,我已禁用 document_test 中的键,将 foreign_key_checks 设置为 0 并将 unique_checks 设置为 0。此 INSERT 命令已在Linux 服务器并没有完成。 SHOW PROCESSLIST 显示状态为“正在发送数据”。 SELECT count(*) FROM document_test; 命令返回 0。但是,我确实从 SHOW TABLE STATUS 命令中看到 document_test 中的行数非零。有趣的是,据推测,行数应该单调增加,但事实并非如此。连续四次查询的结果分别是3299583、3325775、3299730和3341818!

这完全让我感到困惑。有人可以帮我: (1) 是插入数据吗? (2)如何及时完成本次插入? (2) 有没有办法检查这个INSERT INTO SELECT 命令的状态? (“发送数据”之后的下一步)

不幸的是,我在运行此命令之前没有打开慢查询日志和分析。

【问题讨论】:

  • 实际涉及的数据文件有多大?就个人而言,这种规模的东西我会分成更小的批次,即一次 10-100k 行,或者我只是使用备份文件来创建克隆。这可能很简单,因为您的 MySQL 内存设置太低,无法使这种类型的导入快速运行 - 可能建议增加此查询的可用内存(不知道您是否已经这样做了)
  • 我确实调整了MySQL的内存分配,特别是max_heap_table_size设置为2048M,tmp_table_size设置为2048M,query_cache_limit设置为32M,query_cache_size设置为16M。很久以前我尝试将插入分成小批量,我记得它确实有效,但我不得不手动执行 50 次。有没有办法让它自动化?
  • 我会在例如 php 或 Coldfusion 中创建一个脚本,它会自动执行循环,但是在这种规模的数据库转储(可能)和最安全的方式上,您总是会遇到问题是,如下所述,到 mysqldump 和 LOAD DATA

标签: mysql select insert


【解决方案1】:

也许尝试使用mysqldump 导出数据,然后通过LOAD DATA 导入它?这应该会更快。

【讨论】:

  • 好建议。我正在考虑这样做,但我想使用不同的表名。转储表时是否可以重命名表?
  • 您可以直接转储数据并将其加载到您想要的任何表中:) 如果您擅长手动操作,load data 有选项:INTO TABLE tbl_name 无论如何,您会惊讶于LOAD DATA 的速度有多快是的,相信我。
  • 在我尝试这个之前,我有一个小问题: LOAD DATA 会“知道”它应该将数据输入哪一列吗?我问这个是因为我在创建 document_test 表后创建了一个新列。
  • 当使用 mysqldump 时使用--extended-insert end 然后只是替换列名,因为它将被扩展插入它不会是一项艰巨的任务,从未使用它this 方式,所以我不确定它是否会捕获新列的名称。
  • 刚刚尝试了这个方法,完成了我的任务。即使我没有设置 --extended-insert,转储和导入也快得多。对于 500 万行,转储大约需要 10 分钟,使用 LOAD DATA INFILE 导入大约需要 30 分钟。如果源文件中的列与表中的列不完全匹配(必须在导入前创建),则需要在导入时指定列列表。另一点是当您转储数据时使用完全相同的分隔符(字段由,终止;终止的行)。感谢您帮助我!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-25
  • 1970-01-01
  • 2018-11-06
  • 1970-01-01
  • 1970-01-01
  • 2011-07-12
  • 2014-07-08
相关资源
最近更新 更多