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 編輯過