最近一直在思考一个问题,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 驱动名和数据库 URL
String 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);
//插入sql
String 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,性能不是一个量级