今天要向mysql数据库中导入一个几百MB的csv文件,数据库字段都建好了,怎么导入却是个问题。试了试mysql workbench自带导入功能,不理想,用不了。原因是自带的批量导入的python脚本源码没有考虑字符集的问题,导入结束后会报错,然后再发现只有那么几百行的数据被导入了。显然不行。于是只能靠自己。
以前没有写过导入这么大的文件的代码,试了几种方法,有一种比较好。
第一种方法:读一行insert一行。这种方法效率很低,在我的机器上,大约1000行得导入一分钟。我的是十万行,大约得100分钟也就是约一个半小时。
第二种方法:读1000行,先缓存着,然后insert 前面的1000行,然后再读1000行,再insert。这种方法实验下来比较好。很快,大约2分钟就导入结束了。
第三种方法:读完10万行文件之后,用一个insert语句导入进来。这个方法是理想化了,我试了一下,在我忍受的时间内没有结果,估计很慢。
方法我就试了这么几种,但是具体情况要具体分析,比如我用的是读1000行insert1000行,到底1000这个数字合适不合适呢?到底应该选择多少行当做缓存呢?这个要问问别的高手了,我是小白,啥都不知道。
Ruby代码如下,写的不好别喷我,反正是可以用的:
# -*- coding:utf-8 -*-
require 'mysql2'
client=nil
infile=nil
begin
client = Mysql2::Client.new(:host => "localhost", :username => "root", :password => "", :database => "")
infile=File.new("");
number=1
buffer=""
infile.each do |line|
array=(line.strip+",").split(",")
string="(#{number},'#{array[0]}','#{array[1]}',#{array[2]},'#{array[3]}')"
if(number%1000==0)
buffer+=string
sql="insert into XXX values #{buffer};"
client.query(sql)
buffer=""
puts number
else
buffer+=string+","
end
#puts sql
number+=1
end
sql="insert into XXX values #{buffer.chop};"
client.query(sql)
rescue
#puts "error"
puts $!
puts $@
ensure
client.close
infile.close
end
以下摘自:http://database.51cto.com/art/201010/229046.htm
MySQL提供了另一种解决方案,就是使用一条INSERT语句来插入多条记录。这并不是标准的SQL语法,因此只能在MySQL中使用。
INSERT INTO users(name, age)
VALUES('姚明', 25), ('比尔.盖茨', 50), ('火星人', 600);
上面的INSERT 语句向users表中连续插入了3条记录。值得注意的是,上面的INSERT语句中的VALUES后必须每一条记录的值放到一对(…)中,中间使用","分割。假设有一个表table1
CREATE TABLE table1(n INT);
如果要向table1中插入5条记录,下面写法是错误的:
INSERT INTO table1 (i) VALUES(1,2,3,4,5);
MySQL将会抛出下面的错误
ERROR 1136: Column count doesn't match value count at row 1
而正确的写法应该是这样:
INSERT INTO t able1(i) VALUES(1),(2),(3),(4),(5);
当然,这种写法也可以省略列名,这样每一对括号里的值的数目必须一致,而且这个数目必须和列数一致。如:
INSERT INTO t able1 VALUES(1),(2),(3),(4),(5);