SQLite性能测试(插入)

发布于:2024-05-16 ⋅ 阅读:(62) ⋅ 点赞:(0)

最近一直在思考一个问题,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());
        }
    }
}

执行测试

  1. 插入一条记录,执行时间 0.002s,感觉还不错,基本无感😎

请添加图片描述

  1. 修改代码,循环插入 1000 条记录,再次测试
//执行插入操作
int rowsInserted = 0;
for (int i = 0; i < 1000; i++) {
    rowsInserted = pstmt.executeUpdate();
}

1.6s 左右,还是相当可以

请添加图片描述

  1. 加大力度继续测试,循环插入100,0000 条记录
 for (int i = 0; i < 1000000; i++) {
 	rowsInserted = pstmt.executeUpdate();
 }

漫长的等待…

这次测试明显不乐观,时长达到了26分钟😥

请添加图片描述

  1. 换个思路——模拟并发开辟几个线程,在多线程下循环插入数据
 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,性能不是一个量级

在这里插入图片描述