您的位置:首页 > 数据库 > MySQL

MySQL导入csv文件

2017-10-27 15:04 411 查看
作为一个ETL开发工程师日常需要经常与数据打交道,就在昨天领导给了一批数据,为csv(150M * 3张)和xlsx(3M)格式。本来就是个简单的数据导入(毕竟数据导入做了不止一次)首先想到的就是使用LOAD DATA 命令导入,大量数据的导入LOAD DATA 效率比 insert 和可视化工具导入 要快很多,没想到这几个文件花费了我将近一天的时间。。。

首先介绍下LOAD DATA 的命令:



每次看这样带各种括号的命令就让人头大,但我们可以简化一下,只保留那些最必要的命令符,则以上命令可以简化如下:

load data infile 'file_name' into table tbl_name

看上去简单多了,就四个关键字,简直跟一般的命令一样,那么这个命令是什么意思呢,就是把名为file_name的文件中的数据加载到名为tbl_name的表格中去。看起来非常的好理解。

二、参数详解

知道了命令的意思,我们接下来再看一下上图中各个可选参数的意思

1)LOW_PRIORITY | CONCURRENT: 这个指定了load data操作与其操作表的线程的优化级关系,根据文档说明,这个只对那些只采用了表级别锁(如MYISAM)的引擎有影响,比如InnoDB使用的是行锁,不受这个影响,具体的来说,使用了LOW_PRIORITY,则本操作会在其它线程完成之后再操作,而CONCURRENT会和其它线程同时进行,这个对性能是有一些影响。

2)LOCAL: 这是个非常重要的关键字,指明了文件的位置,简单的说,如果指定了local,则表示文件位于客户端,如果没有,则表示文件在Server端。同时,这个关键字的使用还会影响到load data命令对于错误数据的处理方式。这两者的主要区别如下:

  a) 如果是指定了local,则数据从客户端读取,文档中的说法是会在服务端的临时目录下创建一份文件的copy,但我在测试的时候并没有发现,如果file_name中是绝对路径就不用解释,如果是相对路径,则文件的位置应该是在客户端程序启动的位置,所以为了保险,一般使用绝对路径。由于涉及到数据传输,所以这种方式会相对来说慢一些。

  b)如果未指定local,则文件应该是直接在服务端,这种情况下如果文件名使用的是相对路径,则又分两种情况,一种是文件名前没有相对目录,则直接是在默认数据库的data目录下查找,如果是指定了相对目录,则从server的data目录下寻找。

  c)如果指定了local,则当某条数据处理有误时,系统把这个错误记录为一个warning,不会影响下一条数据的处理,因为涉及到数据传输。而如果没有指定local,则默认情况下,遇到错误后不会继续执行。

  所以,如果我们是在客户端执行load data命令,一定记得加上local参数。

3)
REPLACE |
 
IGNORE: 这个指定了如果当前的数据跟表中的数据有惟一性冲突的时候,采用什么样的方式,是替换已有还是忽略当前。特别需要说明的是,当这两种方式都未指定时,如果数据来自于客户端,则重复的数据会忽略,如果来源于服务端,则命令将终止执行。


4)PARTITION: 指定具体的分区,由于之前数据库中没用到过分区,个人对这块也不熟悉,所以暂时不解释,等到了解了再补充。

5)CHARACTER SET : 指定编码集,如果文件的编码跟数据库的编码不一致,可能会出现乱码的问题。所以要注意的是,这里指定的是文件的编码集,而不是数据库的。

6)[{FIELDS | COLUMNS}  [TERMINATED BY '
string
']  [[OPTIONALLY] ENCLOSED BY '
char
']
 [ESCAPED BY '
char
'] ]

  这个指定了对于字段的处理方式,FIELDS和COLUMNS应该是用其一即可。TERMINATED表示字段间的分隔符,ENCLOSED BY的意思是字段值由什么符号包围,而ESCAPED表示指定转义字符。

  在不指定这个参数的情况下,默认的字段分隔符是\t, 默认字段值无任何值包围,默认转义字符为\\.(反斜线)

7)  [LINES [STARTING BY '
string
']  [TERMINATED
BY '
string
']]: 

     指定每一行的起始符与终止符,默认情况下,起始符为空,终止符为'\n',对于windows产生的文本文件来说,需要指定换行符为'\r\n'.

8)IGNORE 
number
 LINES: 忽略文件中的前 number 行,通常情况下,我们生成的文件可能有列名,那么要忽略的放在,这儿的值设置为1即可。需要注意的是这里是行的数量,而不是行号。

9)[(
col_name_or_user_var
,...)] : 有的时候我们不需要给所有的字段都填充值,这个时候就可以指定列名,以()将列名括起来,注意这里也可以是用户自定义的用户表达式。

10)  [SET 
col_name
 = 
expr
,...]: 如果在前一步中指定了用户表达式,那么相应就可以使用列名等于用户表达式的方式来指定,这个我没有用过,给出一个官方的示例如下:
 LOAD DATA INFILE 'file.txt' INTO TABLE t1(column1, @var1) SET column2 = @var1/100;


命令介绍完了,就说一下操作中遇到的坑:

1. 由于本人习惯了使用客户端操作,所以前期的LOAD DATA 操作都是在客户端上进行的,在导入150M大小的csv文件时居然出现了"[Error Code: 0, SQL State: 08S01]  Communications link failure" 错误,看到这就想是不是由于客户端与mysql服务器的连接有问题,然后又在cmd命令行中连接上MySQL导入同一个文件,遇到了相同的问题"ERROR 2013 (HY000): Lost
connection to MySQL server during query" 这下就蒙了

,赶紧在网上找找解决方案吧,发现有可能是mysql限制了导入文件的大小,然后按照网上说的方法修改了配置文件(方法见https://www.2cto.com/database/201308/238134.html),然后  还是不行。。。然后我就使用csv文件拆分工具将大文件拆分成小文件,导入成功了。 在后来实验的时候发现是公司网络不好

,然后 
然后我就将需要导入的文件老老实实的放到服务器上。以后再导入数据时  我就首选从服务器上导入了!!!

2.  导入时出现问题:Invalid utf8 character string: '"'   经查找是由于文件中有乱码,所以utf8 不识别,在导入命令上添加 ‘CHARACTER SET 'gbk'’ 就可以了,下图是从网上找的资料

3. 在网上找了几个可能出现的问题及解决方案,顺便写在这:

Error1261(01000):Row XX doesn't contain data for all columns

Method:本错误信息提示第XX行数据不足,查看你数据库表中建立的字段和数据中提供的字段数目是否相同,只有二者数目一致,才可以导入。

Error1366(HY000):Incorrect string value: '\x95F\xBE\xF4\xC6\xFB...' for column'enterprise' at row XX

Method:本错误信息提示第XX行‘enterprise’字段出现不正确的字符,查找之后发现我在这个字段的数据含有2个比较复杂的汉字“旻爵”,可能无法识别,把这2个字去掉之后这个错误便消失了。

 

Error1366(HY000):Incorrect integer value: ' ' for column 'money' at row XX

Method:本错误信息提示第XX行出现不正确的int值,可能原因是数据库“money”字段定义的数据类型是int型,而数据中存储的却不是int型(可能是double型、float型之类的)--这种情况一般是数据类型出现不一致的问题。

 

Error1265(01000):Data truncated for column 'money' at row XX

Method:本错误信息提示第XX行数据被截断,可能原因是数据库中‘money’字段是double型或者float型,但是数据文件中可能存在null值,即这个数据值可能是不存在的,解决方案是将这个缺失的字段补‘0’。

Query OK, 0 rows affected, 0 warnings   若发现导入完成后导入成功的条数为0,有可能是文件字段中存在乱码

  贴一下我导入数据的命令吧

LOAD DATA LOCAL INFILE 'F:\\qiantu\\pageNum1num1.csv'
INTO TABLE test.qiantu_page_number_info_test
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY "\r\n"
ignore 1 lines;

最后最后,一定是比较重要的,建表时一定不要(请注意是一定不要)建好索引,外键约束等等,可以再数据导入完成后添加各种约束,否则数据的导入将会出错,或特别慢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MySQL csv 导入数据