将数据从大约9000万条记录的MySQL表迁移到另一个数据库

时间:2018-02-21 11:38:39

标签: mysql

在过去的一周里,我一直在尝试将包含大约9000万行的数据库从MySQL迁移到新创建的Couchbase实例。我已经在网上研究了这样做的可能解决方案,并发现了一些最终由于内存可用性低而失败的工具。我还读到了有关分区的内容,但我并不是MySQL管理方面的专家,所以这对我的能力来说似乎是一个超出范围。最终我决定实现自己的指定脚本,该脚本将从现有的MySQL表中选择一定数量的数据,为Couchbase新创建的存储桶序列化并插入其中。该工具适用于前500万条记录,但是MySQL的实例需要太长时间才能检索更多记录。

值得一提的是,我工作的MySQL表仅供我使用,因此在迁移过程中不会进行任何更改。

我构建的脚本利用了Select Syntax Documentation中所述的LIMIT OFFSET语句,如下所示:

SELECT * FROM data LIMIT ?,?

通过将选择的起点增加一定量的记录来生成?,?。例如,以下是单个迁移过程可能执行的查询:

SELECT * FROM data LIMIT 0,100000
SELECT * FROM data LIMIT 100000,200000
SELECT * FROM data LIMIT 200000,300000
...

当没有检索到记录时,迁移过程将停止。正如我之前所说,从大约500万的位置开始选择记录的查询花费的时间太长,使迁移过程无法撤销。我没有数据库专家,除了通过MySQL Workbench 6.3 CE创建新的MySQL数据库和表之外什么都没做,并且我的数据没有进行任何优化。我尝试迁移的表包含一列作为键,非空,并具有唯一值。所有其他列都没有启用选项。

我想知道是否有其他方法可以顺序选择数据,因此可以插入而不会重复或损坏。非常感谢任何有关此事的帮助!

2 个答案:

答案 0 :(得分:1)

你错误地做了分页。见Using MySQL LIMIT to Constrain The Number of Rows Returned By SELECT Statement

以下说明了带有两个参数的LIMIT子句语法:

SELECT 
    column1,column2,...
FROM
    table
LIMIT offset , count;
  • 偏移量指定要返回的第一行的偏移量。第一行的偏移量为0,而不是1。
  • count指定要返回的最大行数。

所以你应该有一个固定的页面大小(计数)和一个没有重叠的变量偏移量。

SELECT * FROM data LIMIT 0,100000
SELECT * FROM data LIMIT 100000,100000
SELECT * FROM data LIMIT 200000,100000
....
SELECT * FROM data LIMIT 89900000,100000

答案 1 :(得分:1)

我猜MySQL开始花费很长时间来满足你的LIMIT条款,当它们的数量变大时。 LIMIT就是这么做的。

使用索引列来选择要导出的表的每个段,您会有更好的运气。如果某些段包含的行数少于其他段,则不会造成任何损害。

例如你可以做

SELECT * FROM data WHERE datestamp >= '2017-01-01' AND datestamp < '2017-02-01';
SELECT * FROM data WHERE datestamp >= '2017-02-01' AND datestamp < '2017-03-01';
SELECT * FROM data WHERE datestamp >= '2017-03-01' AND datestamp < '2017-04-01';
SELECT * FROM data WHERE datestamp >= '2017-04-01' AND datestamp < '2017-05-01';
SELECT * FROM data WHERE datestamp >= '2017-05-01' AND datestamp < '2017-06-01';
SELECT * FROM data WHERE datestamp >= '2017-06-01' AND datestamp < '2017-07-01';
 ...

按日历月分解记录(假设您有datestamp列)。

或者,如果您有自动增量主键id列,请尝试使用

SELECT * FROM data WHERE                 id < 100000;
SELECT * FROM data WHERE id>= 100000 AND id < 200000;
SELECT * FROM data WHERE id>= 200000 AND id < 300000;
SELECT * FROM data WHERE id>= 300000 AND id < 400000;
SELECT * FROM data WHERE id>= 400000 AND id < 500000;
SELECT * FROM data WHERE id>= 500000 AND id < 600000;
 ...

完全不同的方法仍然可行。在您的转储程序中

 SELECT * FROM data;

然后让程序每隔n条记录切换到另一个输出文件。例如,伪代码

 rowcount = 100000
 rownum = 0
 rowsleft = rowcount
 open file 'out' + 000000;
 while next input record available {
     read record
     write record
     rownum = rownum + 1
     rowsleft = rowsleft - 1
     if rowsleft <= 1 {
        close file
        open file 'out' + rownum
        rowsleft = rowcount
     }
  }
  close file

这将使用单个MySQL查询,因此您不必担心段。它应该很快。