服务端2月18日 19:19
SQLite 索引如何影响查询性能?什么时候反而会变慢?SQLite 的索引本质上是在表数据之外维护一棵 B-Tree,让查询可以少扫很多行。没有索引时,`WHERE user_id = ?` 可能要从头读到尾;有合适索引时,SQLite 可以沿着树快速定位候选记录。问题在于索引不是越多越好,它会占空间,也会拖慢写入,因为每次 `INSERT`、`UPDATE`、`DELETE` 都要同步维护索引页。
## 先用执行计划确认有没有命中
优化 SQLite 查询不要靠感觉,先看 `EXPLAIN QUERY PLAN`。它会告诉你是全表扫描,还是使用了某个索引。比如下面这个查询,如果 `orders(user_id, created_at)...服务端2月18日 19:19
SQLite 如何处理并发读写?WAL 模式能解决什么问题?SQLite 的并发能力要先说清一个前提:它不是服务器数据库,而是把数据库引擎嵌进应用进程,多个连接最终都在争用同一个数据库文件。所以它的设计目标不是让几百个写请求同时冲进去,而是让读操作尽量轻、写操作尽量安全。实际项目里,只要写入不是持续高峰,SQLite 的多读单写模型通常够用;一旦把它当成 MySQL 那样承接高并发写入,就会很快遇到 `database is locked`。
## SQLite 的锁是怎么变化的
默认回滚日志模式下,SQLite 常见锁状态可以理解为从宽到严逐步升级:`SHARED` 允许多个连接读,`RESERVED` 表示某个连接准备写,`PENDING...服务端2月18日 19:19
如何优化 SQLite 性能?索引、事务和 PRAGMA 怎么用?优化 SQLite 性能,先别急着改一堆 PRAGMA。大多数慢查询来自三个地方:没有合适索引、事务拆得太碎、一次取了太多无用数据。SQLite 很快,但它不是魔法;把查询路径、写入批次和文件维护做好,通常比盲目调参数更稳定。
```sql
EXPLAIN QUERY PLAN
SELECT id, title FROM posts
WHERE user_id = ? AND status = 'published'
ORDER BY created_at DESC
LIMIT 20;
CREATE INDEX idx_posts_user_status_time
ON posts(...服务端2月18日 19:19
SQLite WAL 模式是什么?为什么能提升并发读写?SQLite 的 WAL,全称 Write-Ahead Logging,意思是写操作先追加到 WAL 日志文件,而不是立刻修改主数据库文件。默认回滚日志模式更像“先准备撤销方案,再改原文件”;WAL 模式则是“先把变更写到旁边日志,合适时再合并”。这个变化让读写冲突少很多:读连接继续看主库和某个时间点之前的 WAL,写连接把新内容追加到 `-wal` 文件。
```sql
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA wal_autocheckpoint = 1000;
PRAGMA wal_checkpo...服务端2月18日 19:20
SQLite 支持哪些约束类型?实际建表时怎么取舍?SQLite 常用约束包括 `NOT NULL`、`UNIQUE`、`PRIMARY KEY`、`FOREIGN KEY`、`CHECK` 和 `DEFAULT`。它们的价值不是让建表语句更复杂,而是在数据写入时拦住明显错误。应用层校验会受版本、入口和脚本影响,数据库约束才是最后一道防线。
```sql
PRAGMA foreign_keys = ON;
CREATE TABLE users (
id INTEGER PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
age INTEGER CHECK(age >= 0),
status...服务端2月18日 19:20
SQLite 数据库如何备份和恢复才安全?## SQLite 备份先判断是否在线
SQLite 只有一个数据库文件,看起来复制一下就能备份。但安全备份要先判断数据库是否正在写入。离线数据库直接复制通常没问题;在线数据库如果正在写事务,简单 `cp` 可能拿到不一致的文件。启用 WAL 模式时还要注意 `-wal` 和 `-shm` 文件,漏掉 WAL 可能丢最新数据。
## 什么时候可以直接复制?
如果应用已经停止,或者能保证没有写入,文件复制最简单:
```bash
cp app.db app.backup.db
```
WAL 模式下更稳的做法是先 checkpoint,再复制主库文件:
```bash
sqli...服务端2月18日 19:20
SQLite 内存数据库如何使用?适合哪些场景?## SQLite 内存数据库是什么?
SQLite 内存数据库把整个数据库放在内存里运行,不写入磁盘文件。最常见的连接名是 `:memory:`,它仍然支持表、索引、事务、视图和触发器,只是连接关闭后数据就消失。这个特性很适合临时计算和测试,但不适合保存任何不能丢的数据。
```bash
sqlite3 :memory:
```
```python
import sqlite3
conn = sqlite3.connect(':memory:')
```
它通常比磁盘库快,因为少了磁盘 I/O。但别把它当成性能万能药:SQL 写得差、没有事务、缺索引、应用层循环查询,照样会慢。...服务端2月18日 19:21
SQLite FTS5 全文搜索如何建表、查询和优化?## SQLite FTS5 解决什么问题?
SQLite FTS5 是内置的全文搜索模块,适合在本地数据库里搜索文章、笔记、日志、商品名和离线文档。它和 `LIKE '%关键词%'` 不一样:LIKE 经常扫表,FTS5 会把文本拆成 token 并建立倒排索引,所以长文本检索更快。代价也明显,FTS 表会多占磁盘,写入时还要维护索引;如果只是按 id、状态、邮箱精确查询,普通索引更合适。
## 如何创建和查询 FTS 表?
```sql
CREATE VIRTUAL TABLE articles_fts USING fts5(title, content);
INSERT I...服务端2月18日 19:21
SQLite 数据库怎么做安全防护才够用?SQLite 的安全防护不能只盯着一条 `PRAGMA key`。它是嵌入式数据库,没有内置账号、角色和授权语句,也不会像服务端数据库那样替你隔离网络访问。真正的安全边界通常在三层:数据库文件谁能读、应用代码如何执行 SQL、密钥和备份怎么管理。只要数据库文件能被随便拷走,SQL 写得再漂亮也挡不住离线分析。
## 追问
### SQLite 本身有没有用户权限控制?
没有传统意义上的 `CREATE USER`、`GRANT`、`REVOKE`,权限模型要放在应用层和文件系统层。SQLite 的定位是进程内数据库文件,优势是部署简单、依赖少,代价是它不负责多用户访问控制。取舍是服务...服务端2月18日 19:22
SQLite 触发器怎么写,哪些场景要慎用?SQLite 触发器是在表或视图发生 `INSERT`、`UPDATE`、`DELETE` 时自动执行的一段 SQL。它常用来做审计日志、轻量数据校验、维护冗余字段,或者配合视图实现写入转发。好处是规则离数据很近,不容易被某个业务入口漏掉;坏处是逻辑藏在数据库里,排查问题时经常被忽略。实际项目里,触发器适合放稳定、短小、强约束的逻辑,不适合承载复杂业务流程。
```sql
CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT, updated_at TEXT);
CREATE TABLE audit_log(id INTEGER PR...