发表于: 2018-09-10 23:57:32
1 493
今天完成的事情:
一、了解如何往数据库大批量插入数据的方法
数据库插入或者更新大批量数据的性能优化
1、一条SQL语句插入多条数据
INSERTINTO`insert_table`( `datetime`, `uid`, `content`, `type`)
VALUES( '0', 'userid_0', 'content_0', 0), ( '1', 'userid_1', 'content_1', 1);
2、使用事务可以提高数据的插入效率,这是因为进行一个INSERT操作时,MySQL内部会建立一个事务,在事务内才进行真正插入处理操作。通过使用事务可以减少创建事务的消耗,所有插入都在执行后才进行提交操作。
3、SQL语句是有长度限制,在进行数据合并在同一SQL中务必不能超过SQL长度限制,通过max_allowed_packet配置可以修改,默认是1M,测试时修改为8M。(这个暂时没设置)
代码:
创建一个JDbc工具类 获取数据库连接的操作
package com.DataTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JdbcUtill {
static Connection con; //声明一个连接对象
public static Connection getCon(){
try {
Class.forName("com.mysql.cj.jdbc.Driver");//加载连接MySQL数据库的驱动程序
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try { //通过Drivermanager类的getConnection()方法与指定的数据库建立连接。
con= DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql"+"?serverTimezone=GMT%2B8","root","123456");
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
}
创建一个数据测试类
package com.DataTest;
import java.sql.*;
import java.util.Random;
public class DataTest {
public static void main(String[] args)throws SQLException {
// 开时时间
Long begin = System.currentTimeMillis();
//获取数据库连接
Connection con=JdbcUtill.getCon();
//获取语句接口
Statement statement= con.createStatement();
// 设置事务为非自动提交
con.setAutoCommit(false);
int total=10000;
StringBuilder stringBuilder=new StringBuilder();
String prefix="INSERT INTO STUDENT (name,qq,id)Values";
Random random=new Random();
try {
for(int x=0;x<3000;x++){
for(int y=0;y<total;y++) {
stringBuilder.append("("+"\'小王\'"+","+110 +","+ (x+1)*y*(random.nextLong()) +"),");
}
// 构建完整sql
String sql=prefix+stringBuilder.substring(0,stringBuilder.length()-1);
// 添加执行sql
statement.addBatch(sql);
//执行操作
statement.executeBatch();
// 提交事务
con.commit();
// 清空上一次添加的数据
stringBuilder = new StringBuilder();
}
}
finally {
statement.close();
con.close();
}
long end=System.currentTimeMillis();
System.out.println("共花费时间:"+(begin-end)+"s");
}
}
测试过程中遇到了字符串不好插入的问题,和师兄讨论后,用转义字符解决,还是单引,不知道是什么鬼。
最后往数据库插入了193W条数据,我忘记截图了,大概花费了40多分钟。
明天在项目打完包之后,继续完善下代码测试
二、准备项目打包
完善下自己的代码
重新编写了pojo实体类
package com.SpringAndMybatis.pojo;
public class Student {
private String name;
private int qq;
private String learn_type;
private long entrance_time;
private String school;
private long id;
private String daily_link;
private String wish;
private String senior;
private String way;
private long create_time;
private long update_time;
public Student() {
}
public Student(String name, int qq, String learn_type, long entrance_time, String school, long id, String daily_link, String wish, String senior, String way, long create_time, long update_time) {
this.name = name;
this.qq = qq;
this.learn_type = learn_type;
this.entrance_time = entrance_time;
this.school = school;
this.id = id;
this.daily_link = daily_link;
this.wish = wish;
this.senior=senior;
this.way = way;
this.create_time = create_time;
this.update_time = update_time;
}
public String getSenior() {
return senior;
}
public void setSenior(String senior) {
this.senior = senior;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getQq() {
return qq;
}
public void setQq(int qq) {
this.qq = qq;
}
public String getLearn_type() {
return learn_type;
}
public void setLearn_type(String learn_type) {
this.learn_type = learn_type;
}
public long getEntrance_time() {
return entrance_time;
}
public void setEntrance_time(long entrance_time) {
this.entrance_time = entrance_time;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getDaily_link() {
return daily_link;
}
public void setDaily_link(String daily_link) {
this.daily_link = daily_link;
}
public String getWish() {
return wish;
}
public void setWish(String wish) {
this.wish = wish;
}
public String getWay() {
return way;
}
public void setWay(String way) {
this.way = way;
}
public long getCreate_time() {
return create_time;
}
public void setCreate_time(long create_time) {
this.create_time = create_time;
}
public long getUpdate_time() {
return update_time;
}
public void setUpdate_time(long update_time) {
this.update_time = update_time;
}
@Override
public String toString() {
return "Student[name "+name+" ,qq "+qq+" ,learn_type "+learn_type+" ,entrance_time"+entrance_time+
",school"+school+",id"+id+",daily_link"+daily_link+",wish"+wish+",senior"+senior+",way"+way+",create_time"+create_time+
",update_time"+update_time+"]";
}
}
对Spring 的xml文件中 的datasource的配置重新修改
之前的配置:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
</bean>
这个类实现了javax.sql.DataSource接口,但它并没有提供池化连接的机制,每次调用getConnection()获取新连接时,只是简单地创建一个新的连接。因此,这个数据源类比较适合在单元测试 或简单的独立应用中使用,因为它不需要额外的依赖类。
但是建立与数据库的连接是一项较耗资源的工作,频繁的进行数据库连接建立操作会产生较大的系统开销,为了解决上述问题,可以采用数据库连接池技术
连接池主要的优点有:
① 减少连接创建时间及资源的使用 :因为连接是循环使用的,所以就少了创建连接所需要的时间,更重要的是不会在线程每一次调用JDBC的时候都去创建一个新的连接,造成资源浪费。
②简化的编程模式:当使用连接池时,每一个单独的线程在使用其中的连接时,就能够像创建了一个自己的 JDBC 连接一样操作,允许用户直接使用JDBC编程技术。
注意:每个连到数据库的连接在客户端和服务器端都有花销(内存,CPU,上下文切换等等)。每个连接均会对应用程序和 数据库服务器的可用资源带来一定的限制。不管这些连接是否在做有用的工作,仍将使用这些资源中的相当一部分。
连接池能够使性能最大化,同时还能将资源利用控制在一定的水平之下,如果超过该水平,应用程序将崩溃而不仅仅是变慢。
spring在第三方依赖包中包含了两个数据源的实现类包,其一是Apache的DBCP,其二是 C3P0。可以在Spring配置文件中利用这两者中任何一个配置数据源。
DBCP连接池:
使用连接池的第一项工作就是导包,这里需要的两个jar包分别是:
c3p0所需jar:c3p0-0.9.2.1.jar
c3p0与dbcp区别:
dbcp没有自动的去回收空闲连接的功能 c3p0有自动回收空闲连接功能
两者主要是对数据连接的处理方式不同!C3P0提供最大空闲时间,DBCP提供最大连接数。
前者当连接超过最大空闲连接时间时,当前连接就会被断掉。DBCP当连接数超过最大连接数时,所有连接都会被断开。
hibernate开发组推荐使用c3p0,spring开发组推荐使用dbcp (dbcp连接池有weblogic连接池同样的问题,就是强行关闭连接或数据库重启后,无法reconnect ,告诉连接被重置,这个设置可以解决),hibernate in action推荐使用c3p0和proxool。(这个不知道具体原因)
我配置的是dbcp
三、开始项目打包
在maven中支持打包
列表中maven的命令:
① 清除产生的项目:mvn clean
②验证工程是否正确,所有需要的资源是否可用:mvn validate
③编译源代码:mvn compile
④运行测试:mvn test
⑤打包:mvn package
⑥运行任何检查,验证包是否有效且达到质量标准:mvn verify
⑦把自定义的maven项目,安装至本地仓库:mvn install
⑧ 生成站点目录: mvn site
⑨ 打包后将其安装到pom文件中配置的远程仓库: mvn deploy
还有一些其他的maven常见命令:
mvn -version 查看maven的版本及配置信息
mvn package -Dmaven.test.skip=true 打包项目时跳过单元测试
mvn dependency:list 显示所有已经解析的所有依赖
mvn dependency:analyze 对项目中的依赖进行分析,依赖未使用,使用单未引入
三,附加
mvn tomcat:run 启动tomcat
mvn tomat:run命令,然后就可在浏览器里运行查看了.如果你想要更多的定制,可以在pom.xml文件里加下面配置:
01 02 03 04 org.codehaus.mojo 05 tomcat-maven-plugin 06 07 /web 08 9090 09 10 11 12 当然你也可以在命令里加参数来实现特定的功能,
下面几个比较常用:
1>. 跳过测试:-Dmaven.test.skip(=true)
2>. 指定端口:-Dmaven.tomcat.port=9090
3>. 忽略测试失败:-Dmaven.test.failure.ignore=true 当然,如果你的其它关联项目有过更新的话,一定要在项目根目录下运行mvn clean install来执行更新,再运行mvn tomcat:run使改动生效.
mvnDebug tomcat:run
这条命令主要用来远程测试,它会监听远程测试用的8000端口,在eclipse里打开远程测试后,它就会跑起来了,设断点,调试
mvn dependency:sources
故名思义,有了它,你就不用到处找源码了,运行一下,你项目里所依赖的jar包的源码就都有了
package打包命令
刚开始打包时,出现一个错误
maven 不再支持源选项 1.5。请使用 1.6 或更高版本。
是因为maven默认版本是jdk1.5
所以在pom.xml文件中增加jdk的设置,
更改pom.xml文件 添加
继续打包
又出现了错误
Test set: com.SpringAndMybatis.Mapper.SpringAndMybatisTest
Caused by: java.io.FileNotFoundException: class path resource [ApplicationContext.xml] cannot be opened because it does not exist
测试类出错了?但是我测试运行并没有出错啊,也解析了ApplicationContext.xml啊
更意外的事:怎么打包成功了? 这是什么操作
随后,不小心点了Navicat的更新,我安装的是破解版,一更新,尼玛又用不了。。。心累
明天继续搞把!
明天计划的事情:
一、把项目打包到服务器测试运行
二、尽快结束任务一的其他任务
遇到的问题:
1、数据库表格中的creat_time和updat_time字段类型不大明白
2、大批量插入数据的其他方法,百度了许多,哈哈 水平太差 好多看不明白,唯一一个整明白的,不大有效率
评论