最近一直在思考一个问题,SQLite 做到这么轻量级,那它注定不会像 MySql 一样强性能,那么它的性能怎么样呢?并发量多高呢?
官方解释:
About SQLite
最大数据库大小:281TB
最大行大小:1GB
话不多说,操作!
创建数据库&表
新建db文件,作为存储数据库
创建user表,作为测试数据表
CREATE TABLE "user" (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,age INTEGER NOT NULL
);
新建测试demo
新建maven项目,引入相关依赖
<dependency><groupId>org.xerial</groupId><artifactId>sqlite-jdbc</artifactId><version>3.36.0.3</version>
</dependency>
新建测试case
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;public class SqliteInsertExample {public static void main(String[] args) {String url = "jdbc:sqlite:D:\\env\\SQLite\\data\\user.db";String tableName = "user"; try (Connection conn = DriverManager.getConnection(url);PreparedStatement pstmt = conn.prepareStatement(//插入sql"INSERT INTO " + tableName + " (name, age) VALUES (?,?)")) {pstmt.setString(1, "张三");pstmt.setString(2, "20");// 记录执行开始时间double startTime = System.currentTimeMillis();//执行插入操作int rowsInserted = pstmt.executeUpdate();//记录执行结束时间double endTime = System.currentTimeMillis();double duration = endTime - startTime;if (rowsInserted > 0) {System.out.println("Inserted successfully!");System.out.println("执行时间为:"+duration/1000+"s");}} catch (SQLException e) {System.out.println(e.getMessage());}}
}
执行测试
- 插入一条记录,执行时间 0.002s,感觉还不错,基本无感😎
- 修改代码,循环插入 1000 条记录,再次测试
//执行插入操作
int rowsInserted = 0;
for (int i = 0; i < 1000; i++) {rowsInserted = pstmt.executeUpdate();
}
1.6s 左右,还是相当可以
- 加大力度继续测试,循环插入100,0000 条记录
for (int i = 0; i < 1000000; i++) {rowsInserted = pstmt.executeUpdate();}
漫长的等待…
这次测试明显不乐观,时长达到了26分钟😥
- 换个思路——模拟并发开辟几个线程,在多线程下循环插入数据
public class SqliteInsertExample{public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread thread1 = new Thread(myRunnable);Thread thread2 = new Thread(myRunnable);Thread thread3 = new Thread(myRunnable);Thread thread4 = new Thread(myRunnable);Thread thread5 = new Thread(myRunnable);//开启线程thread1.start();thread2.start();thread3.start();thread4.start();thread5.start();}
}
//线程类class MyRunnable implements Runnable{//插入数据库的代码...}
报错了…5个线程失败两个,在 sql 执行期间会有表锁,看来显然不能这么简单处理
如果一个线程执行完毕后,再启用下一个线程,那么我模拟的多并发就没有了意义
与MySQL做个对比
在刚刚测试中循环插入一百万条数据,执行时长长达26分钟,属实是有些恐怖,那么一样的操作一样的环境,换成 mysql (5.7版本) 会有什么样的结果呢?
引入依赖
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version>
</dependency>
创建库表
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(100) NOT NULL,`age` varchar(100) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
新建测试case
import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.SQLException;public class MysqlInsertExample {public static void main(String[] args) {// JDBC 驱动名和数据库 URLString JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";String DB_URL = "jdbc:mysql://localhost/user";// 数据库的用户名与密码String USER = "root";String PASS = "123456";try {//加载并注册JDBC驱动Class.forName(JDBC_DRIVER);Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);//插入sqlString sql = "INSERT INTO user (name, age) VALUES (?, ?)";PreparedStatement pstmt = conn.prepareStatement(sql);// 设置占位符的值pstmt.setString(1, "李四");pstmt.setString(2, "30");// 记录执行开始时间double startTime = System.currentTimeMillis();//执行插入操作int rowsAffected = 0;for (int i = 0; i < 1000000; i++) {rowsAffected = pstmt.executeUpdate();}//记录执行结束时间double endTime = System.currentTimeMillis();double duration = endTime - startTime;if (rowsAffected > 0) {System.out.println("Inserted successfully!");System.out.println("执行时间为:" + duration / 1000 + "s");}//清理环境,关闭连接pstmt.close();conn.close();} catch (ClassNotFoundException e) {// JDBC 驱动类没有找到e.printStackTrace();} catch (SQLException e) {// 处理 JDBC 错误e.printStackTrace();}}}
7分钟左右,看来还得是MySQL,性能不是一个量级