如何解决Mysql大量数据导入遇到的问题

55次阅读
没有评论

共计 3527 个字符,预计需要花费 9 分钟才能阅读完成。

这篇文章主要介绍如何解决 Mysql 大量数据导入遇到的问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

在项目中,经常会碰到往数据库中导入大量数据,以便利用 sql 进行数据分析。在导入数据的过程中会碰到一些需要解决的问题,这里结合导入一个大约 4G 的 txt 数据的实践,把碰到的问题以及解决方法展现出来,一方面自己做个总结记录,另一方面希望对那些碰到相同问题的朋友有个参考。

我导入的数据是百科的 txt 文件,文件大小有 4G 多,数据有 6500 万余条,每条数据通过换行符分隔。每条数据包含三个字段,字段之间通过 Tab 分隔。将数据取出来的方法我采用的是用一个 TripleData 类来存放这三个字段,字段都用 String,然后将多条数据存到 List TripleData 中,再将 List TripleData 存入 mysql 数据库,分批将所有数据存到 mysql 数据库中。

以上是一个大概的思路,下面是具体导入过程中碰到的问题。

1 数据库连接的乱码及兼容问题。

数据中如果有中文的话,一定要把链接数据库的 url 设置编码的参数,url 设置为如下的形式。

URL= jdbc:mysql:// +IP+ : +PORT+ / +DB_NAME+ ?useSSL=false useUnicode=true characterEncoding=utf-8

把编码设置为 UTF- 8 是解决乱码问题,设置 useSSL 是解决 JDBC 与 mysql 的兼容问题。如果不设置 useSSL,会报错。类似于

Establishing SSL connection without server s identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn t set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to  false . You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

这样的错误信息。主要是 mysql 版本比较高,JDBC 版本比较低,需要兼容。

2 utf8mb4 编码问题

在导入数据的过程中,还会碰到类似于

SQLException :Incorrect string value: \xF0\xA1\x8B\xBE\xE5\xA2… for column name

这样的错误信息,这是由于 mysql 中设置的 utf- 8 是默认 3 个字节的,对于一般的数据是没有问题的,如果是大的数据量,里面难免会包含一些微信表情,或者特殊字符,它们占了 4 个字节,utf- 8 不能处理,所以报错。解决的办法就是 mysql 在 5.5.3 以后的版本引入了 4 个字节的 utf- 8 编码,也就是 utf8mb4,需要对 mysql 的编码重新设置。

可以按照以下步骤进行操作,一是对要修改的数据库进行备份,虽然 utf8mb4 是向下兼容 utf8 的,但为了以防操作不当,还是需要防患于未然,做好备份工作。二是要修改数据库的字符集编码为 utf8mb4—UTF-8 Unicode,排序规则 utf8mb4_general_ci。以上修改我是使用 navicat 进行修改的,如何用命令行修改,大家可以自行查找。三是要修改配置文件 my.ini,在 mysql 安装的根目录下。加入以下设置。

[client]
default-character-set = utf8mb4
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
[mysql]
default-character-set = utf8mb4

修改完成后,需要重新启动 mysql,使修改生效。

然后再进行数据的导入工作,应该就可以正常导入了。

3 大批量导入的时间效率问题

由于我们的数据量比较大,我们把数据进行了分割,我把 6500 万条数据分为 500 个文件,每个文件大约 11 万条数据,将这 11 万条数据放到 ArrayList TripleObject 中,然后批量导入。大概的思路是采用“insert into tb (…) values(…),(…)…;”的方法,用 insert 一次性插入,这样时间会节约很多时间。示例方法如下。

public static void insertSQL(String sql,List TripleObject  tripleObjectList) throws SQLException{
 Connection conn=null;
 PreparedStatement psts=null;
 try { conn=DriverManager.getConnection(Common.URL, Common.DB_USERNAME, Common.DB_PASSWORD);
 conn.setAutoCommit(false); //  设置手动提交  
 //  保存 sql 后缀
 StringBuffer suffix = new StringBuffer();
 int count = 0; 
 psts=conn.prepareStatement( 
 String s= 
 String p= 
 String o= 
 while (count tripleObjectList.size()) { s=tripleObjectList.get(count).getSubject().replaceAll( , ,  .).replaceAll(\\( , ).replaceAll(\\) ,  ).replaceAll(\ , ).replaceAll( \\\\ ,  
 p=tripleObjectList.get(count).getPredicate().replaceAll( , ,  .).replaceAll(\\( , ).replaceAll(\\) ,  ).replaceAll(\ , ).replaceAll( \\\\ ,  
 o=tripleObjectList.get(count).getObject().replaceAll( , ,  .).replaceAll(\\( , ).replaceAll(\\) ,  ).replaceAll(\ , ).replaceAll( \\\\ ,  
 suffix.append((  +s + , +p+ , + o+), 
 count++;
 }
 //  构建完整 SQL
 String allsql = sql + suffix.substring(0, suffix.length() - 1);
 //  添加执行 SQL
 psts.addBatch(allsql);
 psts.executeBatch(); //  执行批量处理  
 conn.commit(); //  提交  
 } catch (Exception e) { e.printStackTrace();
 }finally{ if(psts!=null){ psts.close();
 }
 if(conn!=null){ conn.close();
 }
 }
 }

这种方法的优点是导入数据花费的时间会很少,6500 万条数据,用了正好 1 个小时。缺点是如果数据中有一大段的句子,需要对里面的逗号,括号,反斜线等进行处理,这里需要进行衡量,是否使用该方法。

如果正常插入,也就是使用“insert into tb (…) values(…);insert into tb (…) values(…);……”的形式,则不用处理特殊的符号,但花费的时间会很长,我测试了一下,11 万条数据大约需要 12 分钟左右,导入 6500 万条数据大概要 100 个小时。

我们采用的是第一种方法,数据大概可以查看就可以,对数据要求没有那么严格,节约了时间。

以上是“如何解决 Mysql 大量数据导入遇到的问题”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注丸趣 TV 行业资讯频道!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-04发表,共计3527字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)