SQLite
背景 之前介绍《MQTT,弱网之友 》时提到过开发了一个客户端时用到了 MQTT 协议,同样的,客户端也都需要一个数据库支撑,但是由于 MySQL 比较重,性价比不高。有一个更好的选择,则是天降猛男 SQLite。
介绍 SQLite 是一个轻量级的数据库管理系统,遵守ACID,非常适合于需要一个简单且独立的数据库解决方案的应用。
据不完全统计,SQLite 是世界上使用最多的数据库。说到这里大家可能觉得惊讶,但如果按照部署实例算可能还真是。
一个普通的手机里,除了系统以外,许多第三方应用程序,如社交媒体、邮件客户端、游戏等,都可能内嵌 SQLite 数据库来存储用户数据、缓存、应用设置等,有的应用还会有多个实例。
因此,一个普通的手机就可能存在数十甚至上百个 SQLite 实例。
移动端 APP
优势 SQLite 是一个 用 C 语言编写的轻量级数据库管理系统,主打一个 轻量 ,简单列一下特性。
轻量级:SQLite 不需要单独的服务器进程或系统资源,数据库存储在一个单一的磁盘文件中,这使得它非常适合于小型应用和移动设备 无需配置:SQLite 不需要复杂的安装和配置过程,可以很容易地集成到各种应用程序中。比如 Java 只需要在 pom.xml 引入配置即可 嵌入式:SQLite 是一个嵌入式的库,不作为一个独立的服务运行,而是直接嵌入到应用程序中 事务性:支持 ACID 事务,确保数据的一致性和完整性 零配置:无需运行数据库服务器或进行复杂的配置,SQLite 数据库文件可以被多个进程共享访问 适合嵌入式系统:由于其轻量级和简单性,SQLite 经常用于嵌入式系统和移动应用 应用场景 移动应用:移动应用通常需要一个轻量级的数据库来存储本地数据,SQLite 因其小体积和无需服务器的特性非常适合 轻量级 Web 应用:不需要复杂事务处理或高并发访问的应用 边缘计算:边缘设备上运行 SQLite,仅将重要更改同步到云端,可以有效降低网络带宽的使用,并提高数据处理的实时性 不适合场景 高并发应用:SQLite 不适合需要高并发写入操作的应用场景 分布式系统:SQLite 是一个文件基的数据库,不适合分布式系统或需要跨多个服务器共享数据库的场景 复杂的事务处理:SQLite 处理复杂的事务业务相对其他数据库较弱 语法 SQLite 遵循 SQL 标准的大部分基本语法和功能,如数据定义语言(DDL)、数据操纵语言(DML)、数据查询语言(DQL)等,所以大多数场景下使用跟其他数据库语法基本一致。
简单函数调用
SQL 示例 -- 表创建 CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL , age INTEGER ); -- 列增加 ALTER TABLE table_name ADD COLUMN column_name column_data_type; -- 表删除 DROP TABLE IF EXISTS table_name; -- 增删改查 INSERT INTO users ( name , age) VALUES ( 'wushihong' , 30 ); DELETE FROM users WHERE name = 'wushihong' ; UPDATE users SET age = 31 WHERE name = 'wushihong' ; SELECT name , age FROM users WHERE age > 25 ORDER BY age ASC LIMIT 10 ; -- 索引创建 CREATE INDEX index_name ON table_name (column_name); -- 视图创建 CREATE VIEW v_users_over_25 AS SELECT name , age FROM users WHERE age > 25 ; -- 触发器创建 CREATE TRIGGER trg_users_after_insert AFTER INSERT ON users FOR EACH ROW BEGIN INSERT INTO users_audit (user_id, operation) VALUES (NEW.id, 'INSERT' ); END ;
程序示例(Java) 安装 < dependency > < groupId > org.xerial </ groupId > < artifactId > sqlite-jdbc </ artifactId > < version > 3.36.0.3 </ version > </ dependency >
创建数据库链接 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class SQLiteDemo { public static void main (String[] args) { String url = "jdbc:sqlite:SQLiteDatabase.db" ; // SQLiteDatabase.db 是数据库文件,路径可配置 try (Connection connection = DriverManager.getConnection(url)) { // 连接成功,可以执行数据库操作 } catch (SQLException e) { e.printStackTrace(); } } }
上面执行完后,就会在配置路径下生成一个 SQLiteDatabase.db 文件
如果有安装 SQLite3 的话,也可以通过命令进入指定数据库
sqlite3 SQLiteDatabase.db
之后就可以对数据库进行操作
sqlite3 操作 db
创建表 创建一个名为 users 的表,该表包含 id、name 和 age 三个字段
String sql = "CREATE TABLE IF NOT EXISTS users (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, " + "age INTEGER NOT NULL)" ; try (Statement statement = connection.createStatement()) { statement.execute(sql); } catch (SQLException e) { e.printStackTrace(); }
增删改查 // 新增用户 private static void insertUser (Connection conn, String name, int age) throws SQLException { String sql = "INSERT INTO users(name, age) VALUES(?, ?)" ; try (PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString( 1 , name); pstmt.setInt( 2 , age); pstmt.executeUpdate(); } } // 查询用户 private static Map<String, Object> getUserById (Connection conn, int id) throws SQLException { String sql = "SELECT id, name, age FROM users WHERE id = ?" ; try (PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setInt( 1 , userId); ResultSet rs = pstmt.executeQuery()) { Map<String, Object> resp = new HashMap<>(); while (rs.next()) { resp.put( "id" , rs.getInt( "id" ); resp.put( "name" , rs.getString( "name" )); resp.put( "age" , rs.getInt( "age" )); } return resp; } } // 更新用户 private static void updateUser (Connection conn, String name, int age) throws SQLException { String sql = "UPDATE users SET age = ? WHERE name = ?" ; try (PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setInt( 1 , age); pstmt.setString( 2 , name); pstmt.executeUpdate(); } } // 删除用户 private static void deleteUser (Connection conn, String name) throws SQLException { String sql = "DELETE FROM users WHERE name = ?" ; try (PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString( 1 , name); pstmt.executeUpdate(); } }
另外说明 一般项目使用 SQLite 时,也会整合 SpringBoot、DAO 框架、数据库连接池组件等配套,很少会单独使用。
上面只是为了举例,篇幅有限不一一列举。
使用过程中遇到的问题 时间类型处理问题 SQLite 没有像 MySQL 一样的 DATETIME 数据类型,容易出现时间格式不一致或解析错误的问题
解决:在存储和查询时间数据时,尽量使用统一的时间格式,如 ISO 8601 标准格式(YYYY-MM-DD HH:MM:SS)
查询速度较慢 尽量优化数据量,定期清理不必要的数据,优化数据表结构,避免 db 文件过大 优化查询语句;为经常查询的列创建索引,以提高查询效率 SQLite 在并发访问方面的性能相对较弱,容易出现数据库锁问题,所以尽量减少并发访问,避免长时间的事务操作 DB 文件损坏 某些极端情况下可能会导致 DB 文件损坏,比如断电、文件系统异常、硬件问题等
解决:定期备份、备份恢复
最后 SQLite 作为一个轻量级数据库,对于轻量级应用、移动应用、小型项目的快速开发等场景,SQLite 无疑是最佳选择。但是面对高并发、大规模数据、复杂事务等场景时,SQLite 则不那么适合,毕竟术业有专攻。
还是那句话,选择组件时需要结合整个项目和公司环境考虑,没有一套方案能够适合所有场景。
参考
SQLite: https://www.sqlite.org/docs.html
阅读原文:原文链接
该文章在 2025/1/15 10:12:44 编辑过