在过去的一周里,我一直在尝试将包含大约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数据库和表之外什么都没做,并且我的数据没有进行任何优化。我尝试迁移的表包含一列作为键,非空,并具有唯一值。所有其他列都没有启用选项。
我想知道是否有其他方法可以顺序选择数据,因此可以插入而不会重复或损坏。非常感谢任何有关此事的帮助!
答案 0 :(得分:1)
你错误地做了分页。见Using MySQL LIMIT to Constrain The Number of Rows Returned By SELECT Statement
以下说明了带有两个参数的LIMIT子句语法:
SELECT
column1,column2,...
FROM
table
LIMIT offset , 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查询,因此您不必担心段。它应该很快。