数据存储与访问之——又见SQLite数据库

承接之前对 SQLite 的介绍,这次我们深入探讨 SQLite 在 Android 中的高级用法、优化技巧以及与 SharedPreferences 的对比,保持简洁并聚焦实用内容。如果你对 SQLite 的基础概念(如创建数据库、基本 CRUD 操作)已有了解,以下内容将帮助你进一步掌握其高级应用。

1. 回顾 SQLite 核心特点

  • 轻量级:嵌入式数据库,单文件存储,适合移动设备。
  • SQL 支持:支持标准 SQL,适合结构化数据。
  • 局限性:不支持高并发,适合单用户或低并发场景。
  • 存储路径:Android 中通常位于 /data/data/包名/databases/

2. 高级用法

以下是 SQLite 在 Android 中的高级功能和实现方式:

事务管理

事务可显著提高批量操作性能,减少 I/O 开销。

val db = dbHelper.writableDatabase
db.beginTransaction()
try {
    for (i in 1..1000) {
        val values = ContentValues().apply {
            put("username", "User$i")
            put("age", 20 + i % 10)
        }
        db.insert("users", null, values)
    }
    db.setTransactionSuccessful()
} catch (e: SQLiteException) {
    Log.e("SQLite", "Transaction failed: ${e.message}")
} finally {
    db.endTransaction()
    db.close()
}

复杂查询

支持 JOIN、子查询、聚合函数等。例如,查询年龄大于 20 的用户并按年龄排序:

val db = dbHelper.readableDatabase
val cursor = db.rawQuery(
    "SELECT username, age FROM users WHERE age > ? ORDER BY age DESC",
    arrayOf("20")
)
while (cursor.moveToNext()) {
    val username = cursor.getString(0)
    val age = cursor.getInt(1)
    Log.d("SQLite", "Username: $username, Age: $age")
}
cursor.close()
db.close()

索引优化

为频繁查询的字段创建索引以提升性能。

val db = dbHelper.writableDatabase
db.execSQL("CREATE INDEX idx_username ON users(username)")

数据库升级

通过 SQLiteOpenHelperonUpgrade 方法处理表结构变更。

override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
    if (oldVersion < 2) {
        db.execSQL("ALTER TABLE users ADD COLUMN email TEXT")
    }
    if (oldVersion < 3) {
        db.execSQL("CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT)")
    }
}

数据库备份

复制数据库文件实现备份。

fun backupDatabase(context: Context, dbName: String, backupPath: String) {
    val dbFile = context.getDatabasePath(dbName)
    val backupFile = File(backupPath)
    dbFile.copyTo(backupFile, overwrite = true)
}

3. 与 SharedPreferences 的对比

特性SQLiteSharedPreferences
数据类型结构化数据(表、列、SQL 查询)键值对(基本类型、StringSet)
存储容量适合较大、复杂数据(MB 级)适合少量数据(KB 级)
查询能力支持复杂 SQL 查询(JOIN、聚合等)仅支持键值查询
性能批量操作需事务优化,适合复杂逻辑轻量、快速,适合简单读写
使用场景用户数据、列表、离线缓存用户偏好、简单配置、临时状态
线程安全非线程安全,需手动加锁非线程安全,建议单线程操作
复杂度需手动管理表结构、SQLAPI 简单,无需定义结构

选择建议

  • 用 SQLite:数据量较大、需要复杂查询或关系型存储(如用户列表、订单记录)。
  • 用 SharedPreferences:简单键值对、用户偏好(如主题、开关状态)。
  • 替代方案:考虑 Room(基于 SQLite,类型安全)或 DataStore(现代偏好存储)。

4. 优化技巧

  • 批量操作:使用事务减少 I/O 开销。
  • 索引:为 WHERE、ORDER BY 字段创建索引,但注意索引会增加写入时间。
  • 连接池:避免频繁打开/关闭数据库,复用 SQLiteDatabase 实例。
  • 预编译语句:使用 rawQuerycompileStatement 提高查询效率。
  val stmt = db.compileStatement("INSERT INTO users (username, age) VALUES (?, ?)")
  stmt.bindString(1, "Alice")
  stmt.bindLong(2, 25)
  stmt.executeInsert()
  • 分区存储:大表可按时间或类别分表存储,降低单表查询开销。

5. 注意事项

  • 线程安全:SQLite 非线程安全,建议在单线程或使用锁(如 synchronized)。
  • 异常处理:捕获 SQLiteException,处理磁盘满、权限错误等。
  • 数据安全:敏感数据需加密,可结合 SQLCipher 加密 SQLite 数据库。
  • 数据库大小:监控 .db 文件大小,避免过大影响性能。
  • 迁移到 Room:Room 提供更现代的 API,支持 LiveData 和协程,推荐用于新项目。

6. 实际应用

  • 离线缓存:如新闻列表、聊天记录。
  • 数据管理:用户资料、订单历史。
  • 复杂查询:如按条件过滤、统计分析。

如果需要更详细的代码示例(如 Room 迁移、SQLCipher 集成)、性能测试对比,或特定场景的 SQLite 实现,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注