SQLite全文搜索引擎:实现原理、应用实践和版本差异
文章目录
- 一、实现原理
- 1.1 倒排索引
- 1.2 虚拟表
- 二、应用在工程上的实施方法
- 2.1 创建FTS虚拟表
- 2.2 插入数据
- 2.3 全文搜索
- 2.4 关联普通表
- 2.5 更新和删除数据
- 2.6 优化FTS虚拟表
- 2.7 小结
- 三、FTS3、FTS4和FTS5的区别
- 3.1 FTS3
- 3.2 FTS4
- 3.3 FTS5
- 3.4 小结
- 四、更新SQLite的FTS版本的步骤
- 4.1 备份现有数据
- 4.2 创建新的FTS虚拟表
- 4.3 迁移数据
- 4.4 更新关联的普通表
- 4.5 删除原始FTS虚拟表
- 4.6 修改应用程序代码
- 4.7 小结
- 五、总结
SQLite的全文搜索(Full-Text Search,简称FTS)是一种高效的全文搜索技术,基于倒排索引(Inverted Index)实现,用于在大量文本数据中快速找到包含特定词汇的记录。FTS在SQLite中作为一个虚拟表(Virtual Table)模块实现,支持多种版本,如FTS3、FTS4和FTS5。
一、实现原理
1.1 倒排索引
FTS的核心是倒排索引,它是一种将词汇映射到出现该词汇的文档集合的数据结构。在创建FTS虚拟表时,SQLite会为每个词汇生成一个倒排索引,记录该词汇在哪些文档(即数据库记录)中出现。倒排索引使得全文搜索能够快速找到包含特定词汇的文档,而无需遍历整个数据库。
以下是倒排索引的构建算法:
-
文档预处理:首先对文档进行预处理,包括去除标点符号、转换为小写字母等,以便后续分词和构建索引。
-
分词:将预处理后的文本拆分成词汇(Token)。分词方法因语言和应用场景而异,常见的分词器有空格分词器(以空格为分隔符)、正则表达式分词器、N-gram分词器、自然语言处理分词器等。SQLite支持多种分词器,如简单分词器(simple tokenizer)、Unicode61分词器(unicode61 tokenizer)和自定义分词器。分词器的选择会影响FTS的搜索效果和性能。
-
构建词汇表:遍历所有文档的词汇,构建一个词汇表,包含所有不重复的词汇。词汇表通常使用字典(Dictionary)或哈希表(Hash Table)等数据结构存储,以便快速查找特定词汇。
-
构建倒排列表:为每个词汇构建一个倒排列表,记录包含该词汇的所有文档ID。倒排列表可以使用链表、数组或其他数据结构存储。为提高查找效率,倒排列表中的文档ID通常按照升序排列。
-
构建倒排索引:将词汇表和倒排列表组合成一个倒排索引。倒排索引可以使用字典(Dictionary)或哈希表(Hash Table)等数据结构存储,其中键(Key)为词汇,值(Value)为对应的倒排列表。
通过以上算法,可以构建一个倒排索引,实现高效的全文搜索。在实际应用中,还可以对倒排索引进行优化,如压缩倒排列表以减少存储空间需求、为频繁出现的词汇添加倒排列表缓存以提高查找速度等。此外,倒排索引的更新(插入、删除和修改文档)也是一个重要问题,通常可以通过增量式更新或定期重建索引等方法实现。
1.2 虚拟表
FTS虚拟表(Full-Text Search Virtual Table)是SQLite中实现全文搜索的一种特殊表结构。它用于存储全文索引数据,包括倒排索引的信息。虽然FTS虚拟表在查询时表现得像普通的SQLite表,但其实现和存储方式与普通表有很大不同。
FTS虚拟表的结构主要包括以下几个部分:
-
词汇表:词汇表是一个包含所有不重复词汇的列表,用于映射词汇到其对应的倒排列表。在SQLite中,词汇表通常使用B树(B-Tree)或哈希表(Hash Table)等数据结构实现,以支持高效的查找和插入操作。
-
倒排列表:倒排列表是一个记录包含特定词汇的所有文档ID的列表。在SQLite中,倒排列表通常使用链表、数组或其他数据结构存储。为提高查找效率,倒排列表中的文档ID通常按照升序排列。
-
文档元数据:FTS虚拟表还存储了一些文档的元数据,如文档ID(docid)和词汇在文档中的位置信息。这些元数据有助于在全文搜索时获取相关记录的详细信息,并支持高级搜索功能,如短语搜索和邻近搜索。
FTS虚拟表如何存储倒排索引的数据:
在SQLite中,FTS虚拟表使用B树(B-Tree)作为底层存储结构,以高效地存储和检索倒排索引数据。具体来说,FTS虚拟表将词汇表、倒排列表和文档元数据存储在一个或多个B树中,通过B树的键(Key)和值(Value)关联各个部分的数据。
以下是FTS虚拟表存储倒排索引数据的一般过程:
-
对于词汇表,FTS虚拟表将词汇作为B树的键(Key),并将指向对应倒排列表的指针作为值(Value)。
-
对于倒排列表,FTS虚拟表将每个文档ID作为B树的键(Key),并将词汇在文档中的位置信息作为值(Value)。
-
对于文档元数据,FTS虚拟表将文档ID(docid)作为B树的键(Key),并将其他元数据(如词汇位置信息)作为值(Value)。
在实际应用中,FTS虚拟表的存储结构可能因版本(如FTS3、FTS4和FTS5)和配置选项(如分词器和压缩存储格式)而有所不同。然而,其核心思想是利用B树等高效的数据结构存储和检索倒排索引数据,以实现高性能的全文搜索功能。
二、应用在工程上的实施方法
2.1 创建FTS虚拟表
要使用FTS功能,首先需要创建一个FTS虚拟表。创建FTS虚拟表的语法与创建普通表类似,但需要使用VIRTUAL TABLE
关键字,并指定FTS模块(如FTS3、FTS4或FTS5)。例如:
CREATE VIRTUAL TABLE articles USING fts4(title, content);
上述语句创建了一个名为articles
的FTS虚拟表,包含title
和content
两个全文索引字段。
2.2 插入数据
向FTS虚拟表插入数据与向普通表插入数据类似。例如:
INSERT INTO articles(title, content) VALUES('Hello World', 'This is a test article about SQLite FTS.');
需要注意的是,向FTS虚拟表插入数据时,SQLite会自动对全文索引字段进行分词和倒排索引的构建。
2.3 全文搜索
使用FTS虚拟表进行全文搜索时,可以使用MATCH
操作符。例如:
SELECT * FROM articles WHERE title MATCH 'SQLite';
上述语句将返回所有title
字段包含“SQLite”的记录。也可以使用AND
、OR
和NOT
操作符组合多个词汇进行复杂的全文搜索。
2.4 关联普通表
为了在全文搜索时获取相关记录的详细信息,可以将FTS虚拟表与普通表关联。通常,可以在普通表中添加一个与FTS虚拟表对应的docid
字段,用于存储FTS虚拟表中的记录ID。然后,在查询时使用JOIN
操作符关联两个表。例如:
SELECT articles.*, details.* FROM articles JOIN details ON articles.docid = details.id WHERE articles.title MATCH 'SQLite';
上述语句将返回所有title
字段包含“SQLite”的记录,以及与这些记录关联的详细信息。
2.5 更新和删除数据
更新和删除FTS虚拟表中的数据与普通表类似,可以使用UPDATE
和DELETE
语句。需要注意的是,在更新或删除FTS虚拟表中的数据时,也要同步更新或删除关联的普通表中的数据。例如:
UPDATE articles SET title = 'New Title' WHERE docid = 1;
DELETE FROM articles WHERE docid = 2;
2.6 优化FTS虚拟表
为了提高FTS虚拟表的性能和存储效率,可以定期对其进行优化。在SQLite中,可以使用OPTIMIZE
命令优化FTS虚拟表。例如:
INSERT INTO articles(articles) VALUES('optimize');
上述语句将对articles
虚拟表进行优化。优化过程可能需要一些时间,因此建议在数据库空闲时执行。
2.7 小结
通过以上实施方法,可以在工程项目中应用SQLite的FTS功能,实现高效的全文搜索。在实际应用中,根据项目需求和数据量,可以选择合适的FTS模块、分词器和优化策略,以获得最佳的全文搜索性能。
三、FTS3、FTS4和FTS5的区别
FTS3、FTS4和FTS5都是SQLite的全文搜索(Full-Text Search)引擎,用于实现高效的全文搜索功能。它们之间的主要区别在于功能和性能方面的改进。
3.1 FTS3
FTS3是SQLite的第一个全文搜索引擎,提供基本的全文搜索功能。它支持倒排索引(Inverted Index)和多种分词器(Tokenizer)。FTS3虚拟表可以与普通表关联,以便在全文搜索时获取相关记录的详细信息。FTS3引擎支持基本的全文搜索查询,如MATCH
操作符和布尔操作符(AND
、OR
和NOT
)。
3.2 FTS4
FTS4在FTS3的基础上进行了改进,增加了一些新功能。主要区别包括:
- 支持外部内容表(External Content Tables),允许将FTS虚拟表与普通表关联,以便在全文搜索时获取相关记录的详细信息。
- 支持增量式更新(Incremental Updates),允许在FTS虚拟表中插入、更新和删除记录,而不需要重建整个倒排索引。
- 支持自定义分词器(Custom Tokenizers),允许用户自定义分词规则,以适应不同语言和应用场景。
- 支持可选的压缩存储格式(Compressed Storage Format),可以减少FTS虚拟表的存储空间需求。
3.3 FTS5
FTS5是SQLite的最新全文搜索引擎,相较于FTS4,它引入了更多的改进和新功能。主要区别包括:
- 更高的查询性能,尤其是在处理大型文档集合时。
- 支持更灵活的查询语法,如近义词查询(Synonym Queries)和自定义排序规则(Custom Ranking Functions)。
- 支持更多的分词器选项,如Unicode61分词器(unicode61 tokenizer),支持Unicode 6.1及以上版本的字符集。
- 改进了外部内容表(External Content Tables)的实现,提高了与普通表关联时的查询性能。
3.4 小结
总之,FTS3、FTS4和FTS5是SQLite全文搜索引擎的不同版本,它们之间的主要区别在于功能和性能方面的改进。在实际应用中,建议使用最新的FTS5引擎,以获得更好的全文搜索性能和功能。然而,如果项目已经在使用FTS3或FTS4,并且不需要FTS5的新功能,可以继续使用现有的引擎。
四、更新SQLite的FTS版本的步骤
要更新SQLite的FTS版本,需要遵循以下步骤。以下示例说明了如何从FTS4升级到FTS5,但这些步骤也适用于从FTS3升级到FTS4或FTS5。
4.1 备份现有数据
在执行任何升级操作之前,建议备份现有的FTS虚拟表和关联的普通表,以防止数据丢失。
4.2 创建新的FTS虚拟表
使用新的FTS版本创建一个新的FTS虚拟表。例如,要创建一个FTS5虚拟表,可以使用以下SQL语句:
CREATE VIRTUAL TABLE new_articles USING fts5(title, content);
这将创建一个名为new_articles
的FTS5虚拟表,包含title
和content
两个全文索引字段。
4.3 迁移数据
将原始FTS虚拟表中的数据迁移到新的FTS虚拟表中。可以使用INSERT INTO ... SELECT
语句实现:
INSERT INTO new_articles(title, content) SELECT title, content FROM old_articles;
这将把原始FTS4虚拟表old_articles
中的所有数据迁移到新的FTS5虚拟表new_articles
中。
4.4 更新关联的普通表
如果原始FTS虚拟表与普通表关联,需要更新关联关系,使普通表指向新的FTS虚拟表。这可能涉及修改普通表中的外键约束或触发器等。
4.5 删除原始FTS虚拟表
在确保新的FTS虚拟表正常工作后,可以删除原始FTS虚拟表以释放存储空间。例如:
DROP TABLE old_articles;
4.6 修改应用程序代码
根据需要,更新应用程序代码以使用新的FTS虚拟表和新的FTS版本提供的功能。
4.7 小结
通过以上步骤,可以将SQLite的FTS版本从FTS3或FTS4升级到FTS4或FTS5。在执行升级操作时,请务必先备份数据,并在测试环境中验证升级后的功能和性能,以确保平滑过渡。
五、总结
SQLite的FTS引擎为开发者提供了强大的全文搜索功能,通过了解其实现原理和应用实践,可以充分利用FTS引擎的优势,提高应用程序的性能和用户体验。在实际项目中,选择合适的FTS版本和优化策略,以满足不同的需求和数据量。
相关文章:
SQLite全文搜索引擎:实现原理、应用实践和版本差异
文章目录 一、实现原理1.1 倒排索引1.2 虚拟表 二、应用在工程上的实施方法2.1 创建FTS虚拟表2.2 插入数据2.3 全文搜索2.4 关联普通表2.5 更新和删除数据2.6 优化FTS虚拟表2.7 小结 三、FTS3、FTS4和FTS5的区别3.1 FTS33.2 FTS43.3 FTS53.4 小结 四、更新SQLite的FTS版本的步骤…...
day17-二叉树part04
110.平衡二叉树 (优先掌握递归)后序遍历 左右中 class Solution {public boolean isBalanced(TreeNode root) {return getHeight(root) ! -1;}//递归三部曲 确定方法的参数与返回值private int getHeight(TreeNode root){//明确终止条件if(root null){r…...

书生浦语第一次课
模型的发展 从专业模型到通用模型 书生浦语大模型全链路开源体系 2023.06.07 -> InternLM千亿参数语言大模型发布 2023.07.06 -> InternLM千亿参数语言大模型全面升级,支持8K语境、26种语言。全面开源、免费商用:InternLM-7B、全链条开源工具…...

UE小:UE5.3无法创建C++工程
当您在使用Unreal Engine (UE) 构建项目时,如果遇到以下问题: Running C:/Program Files/Epic Games/UE\_5.3/Engine/Build/BatchFiles/Build.bat -projectfiles -project"C:/UEProject/Shp\_1/Shp\_1.uproject" -game -rocket -progress Usi…...

FFmpeg获取视频详情
话不多说,直接上代码: pom依赖: <!--视频多媒体工具包 包含 FFmpeg、OpenCV--><dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.3</versi…...
find: paths must precede expression
find: paths must precede expression 1. find: paths must precede expression2. 请在搜索字符串上添加单引号或者双引号References 1. find: paths must precede expression strongforeverstrong:~/ForeverStrong$ find /home/strong/ForeverStrong/image_results/ -name *.…...

RabbitMQ3.x之九_Docker中安装RabbitMQ
RabbitMQ3.x之_Docker中安装RabbitMQ 文章目录 RabbitMQ3.x之_Docker中安装RabbitMQ1. 官网2. 安装1 .拉取镜像2. 运行容器 3. 访问 1. 官网 rabbitmq - Official Image | Docker Hub 2. 安装 1 .拉取镜像 docker pull rabbitmq:3.13.0-management2. 运行容器 # latest Rabb…...

vue快速入门(四)v-html
注释很详细,直接上代码 上一篇 新增内容 使用v-html将文本以html的方式显示 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, …...

第19次修改了可删除可持久保存的前端html备忘录:换了一个特别的倒计时时钟
第19次修改了可删除可持久保存的前端html备忘录:换了一个特别的倒计时时钟 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><met…...

C++ 2024-4-1 作业
#include <iostream> using namespace std;class A { public:int a;A(int a):a(a){cout<<"A的有参构造"<<endl;} }; class B:virtual public A { public:int b;B(int a,int b):A(a),b(b){cout<<"B的有参构造"<<endl;} }; cl…...

【滑动窗口】Leetcode 串联所有单词的子串
题目解析 30. 串联所有单词的子串 本题的意思就是在目标串s中寻找能够找到的words字符串的全排列,返回起始位置 算法讲解 我们可以将这道题转化为寻找目标串的words字母的异位词,按照上一次讲解的【滑动窗口】Leetcode 找到字符串中所有字母异位词我们…...
golang channel实践代码及注意事项
在使用Go语言(Golang)的通道(Channel)时,有几个重要的注意点可以帮助开发者更安全、高效地使用它们进行并发编程。以下是一些关键的注意事项: 选择正确的通道类型:Go语言提供了两种类型的通道&…...

面试题:RabbitMQ 消息队列中间件
1. 确保消息不丢失 生产者确认机制 确保生产者的消息能到达队列,如果报错可以先记录到日志中,再去修复数据持久化功能 确保消息未消费前在队列中不会丢失,其中的交换机、队列、和消息都要做持久化消费者确认机制 由spring确认消息处理成功后…...
wpf中引用自定义字体
在WPF(Windows Presentation Foundation)中,FontFamily属性用于指定控件或文本元素使用的字体。它是一个非常基础且重要的属性,影响着用户界面的视觉呈现和可读性。以下是关于WPF中FontFamily属性的一些关键信息和使用方法&#x…...

高效准确!指甲剪盖片视觉检测技术解密
指甲剪的盖片是指指甲剪的一端,通常用来盖住另一端的刀刃部分。指甲剪盖片是指甲剪的重要部分,除了保护刀刃外,还起到美观和便捷的作用。正确使用和保养指甲剪盖片可以延长指甲剪的使用寿命。 本案是对指甲剪盖片最大尺寸长75mm*宽10mm*高3mm…...
分布式IO模块PLC扩展模拟量模块
BL200是一款结构紧凑、体积小的分布式IO耦合器,支持ModbusTCP协议,采用嵌入式硬件,主频380Mhz,基于LinuxOS,采用独特的MAC层数据交换技术的双网口技术实现级联,中间设备宕机不影响后面设备的数据传输,可支持高达32个AI、DI、DO、热电阻、热电偶、RS485等种类的IO板,广泛应用于工…...
Qt事件系统
第三章Qt事件系统 文章目录 第三章Qt事件系统1.事件系统事件是如何传递的事件类型事件处理发送事件 2.事件传播机制事件接受和忽略事件分发事件过滤 3.事件和信号的区别 1.事件系统 在Qt中,事件是派生抽象QEvent类的对象,它表示应用程序内发生的事情&am…...

C++STL--排序算法
sort 使用快速排序,平均性能好O(nlogn),但最差情况可能很差O(n^2)。不稳定。 sort(v.begin(),v.end());//对v容器进行排序,默认升序 sort(v.begin(),v.end(),greater<int>());//降序排序对于支持随机访问的迭代器的容器, 都可以利用sort算法直接对其进行排序…...

CEF的了解
(14 封私信 / 80 条消息) CEF和Electron的区别是什么? - 知乎 (zhihu.com) Electron面向的开发者:会用JavaScript,HTML,CSS,不会C CEF面向的开发者:会用JavaScript,HTML,CSS,会C (14 封私信 / 80 条消息) liulun - …...

基于OrangePi Zero2的智能家居项目(开发阶段)
智能家居项目的软件实现 紧接上文 基于OrangePi Zero2的智能家居项目(准备阶段)-CSDN博客 目录 一、项目整体设计 1.1项目整体设计 1.2具体划分 二、开发工作的前期准备 1、进行分类,并用Makefile文件进行管理 参考:自己创…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...