SQLite全文搜索 #
一、全文搜索概述 #
1.1 什么是全文搜索 #
sql
-- 全文搜索(Full-Text Search, FTS)
-- 用于在大量文本中快速搜索关键词
-- SQLite 提供 FTS 扩展:
-- FTS3 - 基础版本
-- FTS4 - 增强版本
-- FTS5 - 最新版本(推荐)
1.2 FTS版本对比 #
text
FTS版本对比:
├── FTS3
│ ├── 基础全文搜索
│ └── 所有SQLite版本支持
├── FTS4
│ ├── 增强功能
│ ├── 支持短语查询
│ └── 支持前缀查询
└── FTS5
├── 最新版本
├── 更好的性能
├── 更多功能
└── SQLite 3.9.0+
二、创建FTS表 #
2.1 FTS5基本创建 #
sql
-- 创建FTS5虚拟表
CREATE VIRTUAL TABLE articles USING fts5(
title,
content,
author
);
-- 插入数据
INSERT INTO articles (title, content, author) VALUES
('SQLite Tutorial', 'SQLite is a lightweight database', 'John'),
('Python Guide', 'Python is a programming language', 'Jane'),
('Database Design', 'Learn database design principles', 'Bob');
-- 全文搜索
SELECT * FROM articles WHERE articles MATCH 'SQLite';
2.2 FTS4创建 #
sql
-- 创建FTS4虚拟表
CREATE VIRTUAL TABLE articles_fts4 USING fts4(
title,
content,
author
);
-- 插入数据
INSERT INTO articles_fts4 (title, content, author) VALUES
('SQLite Tutorial', 'SQLite is a lightweight database', 'John');
-- 搜索
SELECT * FROM articles_fts4 WHERE content MATCH 'database';
2.3 FTS3创建 #
sql
-- 创建FTS3虚拟表
CREATE VIRTUAL TABLE articles_fts3 USING fts3(
title,
content
);
三、基本搜索 #
3.1 MATCH搜索 #
sql
-- 基本搜索
SELECT * FROM articles WHERE articles MATCH 'SQLite';
-- 指定列搜索
SELECT * FROM articles WHERE title MATCH 'SQLite';
-- 多个关键词(AND)
SELECT * FROM articles WHERE articles MATCH 'SQLite database';
-- 多个关键词(OR)
SELECT * FROM articles WHERE articles MATCH 'SQLite OR database';
-- 排除关键词
SELECT * FROM articles WHERE articles MATCH 'database NOT SQLite';
3.2 短语搜索 #
sql
-- 精确短语搜索(使用引号)
SELECT * FROM articles WHERE articles MATCH '"lightweight database"';
-- FTS5短语搜索
SELECT * FROM articles WHERE articles MATCH '"database design"';
3.3 前缀搜索 #
sql
-- 前缀搜索(使用*)
SELECT * FROM articles WHERE articles MATCH 'data*';
-- 匹配:data, database, design 等
3.4 NEAR搜索 #
sql
-- NEAR搜索(关键词在指定距离内)
SELECT * FROM articles WHERE articles MATCH 'SQLite NEAR database';
-- 指定距离
SELECT * FROM articles WHERE articles MATCH 'SQLite NEAR/3 database';
-- SQLite和database之间最多3个词
四、高级搜索 #
4.1 列限定搜索 #
sql
-- FTS5列限定语法
SELECT * FROM articles WHERE articles MATCH 'title:SQLite';
-- 多列搜索
SELECT * FROM articles WHERE articles MATCH 'title:SQLite OR content:database';
4.2 布尔查询 #
sql
-- AND(默认)
SELECT * FROM articles WHERE articles MATCH 'SQLite AND database';
-- OR
SELECT * FROM articles WHERE articles MATCH 'SQLite OR MySQL';
-- NOT
SELECT * FROM articles WHERE articles MATCH 'database NOT MySQL';
4.3 括号分组 #
sql
-- 使用括号分组
SELECT * FROM articles
WHERE articles MATCH '(SQLite OR MySQL) AND database';
五、排序和排名 #
5.1 按相关性排序 #
sql
-- FTS5使用bm25排名函数
SELECT
title,
bm25(articles) AS rank
FROM articles
WHERE articles MATCH 'database'
ORDER BY rank;
-- 更简单的写法
SELECT * FROM articles
WHERE articles MATCH 'database'
ORDER BY rank;
5.2 高亮显示 #
sql
-- FTS5高亮函数
SELECT
highlight(articles, 0, '<b>', '</b>') AS title_highlight,
snippet(articles, 1, '<b>', '</b>', '...', 20) AS content_snippet
FROM articles
WHERE articles MATCH 'database';
六、FTS5特殊功能 #
6.1 分词器 #
sql
-- 默认分词器
CREATE VIRTUAL TABLE docs USING fts5(content);
-- Unicode分词器
CREATE VIRTUAL TABLE docs USING fts5(content, tokenize='unicode61');
-- Porter分词器(英文词干提取)
CREATE VIRTUAL TABLE docs USING fts5(content, tokenize='porter unicode61');
-- 中文分词(需要扩展)
-- 使用jieba等分词器
6.2 内容表选项 #
sql
-- 外部内容表
CREATE TABLE articles_content (
id INTEGER PRIMARY KEY,
title TEXT,
content TEXT
);
CREATE VIRTUAL TABLE articles_fts USING fts5(
title,
content,
content='articles_content',
content_rowid='id'
);
-- 自动同步触发器
CREATE TRIGGER articles_ai AFTER INSERT ON articles_content BEGIN
INSERT INTO articles_fts(rowid, title, content)
VALUES (new.id, new.title, new.content);
END;
CREATE TRIGGER articles_ad AFTER DELETE ON articles_content BEGIN
INSERT INTO articles_fts(articles_fts, rowid, title, content)
VALUES ('delete', old.id, old.title, old.content);
END;
CREATE TRIGGER articles_au AFTER UPDATE ON articles_content BEGIN
INSERT INTO articles_fts(articles_fts, rowid, title, content)
VALUES ('delete', old.id, old.title, old.content);
INSERT INTO articles_fts(rowid, title, content)
VALUES (new.id, new.title, new.content);
END;
6.3 无内容表 #
sql
-- 无内容表(只存储索引)
CREATE VIRTUAL TABLE docs USING fts5(content, content='');
七、维护操作 #
7.1 重建索引 #
sql
-- FTS5重建索引
INSERT INTO articles(articles) VALUES('rebuild');
-- 优化
INSERT INTO articles(articles) VALUES('optimize');
-- 合并段
INSERT INTO articles(articles) VALUES('merge');
7.2 删除数据 #
sql
-- 删除特定行
DELETE FROM articles WHERE rowid = 1;
-- 清空表
DELETE FROM articles;
八、实际应用示例 #
8.1 文章搜索系统 #
sql
-- 创建文章表
CREATE TABLE posts (
id INTEGER PRIMARY KEY,
title TEXT,
content TEXT,
author TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 创建FTS索引
CREATE VIRTUAL TABLE posts_fts USING fts5(
title,
content,
content='posts',
content_rowid='id'
);
-- 创建同步触发器
CREATE TRIGGER posts_ai AFTER INSERT ON posts BEGIN
INSERT INTO posts_fts(rowid, title, content)
VALUES (new.id, new.title, new.content);
END;
CREATE TRIGGER posts_ad AFTER DELETE ON posts BEGIN
INSERT INTO posts_fts(posts_fts, rowid, title, content)
VALUES ('delete', old.id, old.title, old.content);
END;
CREATE TRIGGER posts_au AFTER UPDATE ON posts BEGIN
INSERT INTO posts_fts(posts_fts, rowid, title, content)
VALUES ('delete', old.id, old.title, old.content);
INSERT INTO posts_fts(rowid, title, content)
VALUES (new.id, new.title, new.content);
END;
-- 搜索文章
SELECT
p.id,
p.title,
highlight(posts_fts, 1, '<mark>', '</mark>') AS content_highlight,
p.author
FROM posts p
JOIN posts_fts fts ON p.id = fts.rowid
WHERE posts_fts MATCH 'database'
ORDER BY rank;
8.2 产品搜索 #
sql
-- 产品搜索
CREATE VIRTUAL TABLE products_fts USING fts5(
name,
description,
category
);
INSERT INTO products_fts VALUES
('iPhone 15', 'Latest Apple smartphone with A17 chip', 'Electronics'),
('MacBook Pro', 'Professional laptop with M3 chip', 'Electronics'),
('AirPods Pro', 'Wireless earbuds with noise cancellation', 'Audio');
-- 搜索产品
SELECT name, description
FROM products_fts
WHERE products_fts MATCH 'Apple OR chip';
九、性能优化 #
9.1 使用正确的分词器 #
sql
-- 英文使用porter分词器
CREATE VIRTUAL TABLE docs_en USING fts5(content, tokenize='porter unicode61');
-- 中文使用合适的分词器
-- 需要安装扩展
9.2 批量插入 #
sql
-- 批量插入时使用事务
BEGIN;
INSERT INTO articles VALUES (...);
INSERT INTO articles VALUES (...);
...
COMMIT;
9.3 定期优化 #
sql
-- 定期执行优化
INSERT INTO articles(articles) VALUES('optimize');
十、总结 #
FTS版本选择 #
| 版本 | SQLite版本 | 推荐场景 |
|---|---|---|
| FTS3 | 所有版本 | 兼容性要求高 |
| FTS4 | 3.7.4+ | 中等功能需求 |
| FTS5 | 3.9.0+ | 新项目(推荐) |
最佳实践 #
- 使用FTS5获得最佳性能
- 使用外部内容表保持数据同步
- 选择合适的分词器
- 使用bm25进行相关性排序
- 定期优化索引
下一步,让我们学习CTE递归查询!
最后更新:2026-03-27