FTS 虚拟表(Full-Text Search Virtual Table) 是 SQLite数据库中一种特殊表类型,专门用于支持全文搜索功能。理解 FTS虚拟表的概念对于充分利用 SQLite和 Android Room的全文搜索功能至关重要。

以下是关于 FTS 虚拟表的关键点:

  1. 虚拟表的概念
    虚拟表不是实际存储数据的物理表,而是一个接口,背后由特定的模块实现。
    FTS 虚拟表看起来像普通的 SQLite 表,但其内部实现了特殊的索引和搜索算法
  1. 全文搜索功能
    FTS 虚拟表专门优化用于文本搜索,可以快速在大量文本数据中查找关键词。
    它支持复杂的查询,如短语搜索、前缀匹配、布尔操作等。
  1. 索引机制:
    FTS 虚拟表使用倒排索引(Inverted Index)来加速搜索。
    这种索引结构允许快速定位包含特定词语的文档,大大提高了搜索效率。

那么如何创建FTS 表呢?
在 SQLite 中,使用特殊的语法即可创建FTS 表:

CREATE TABLE table_name_fts USING fts4(table_cloumn1, table_cloumn2)

如果是在 Android Room 数据库中,直接可以使用 @Fts3或者@Fts4注解即可:

@Fts4
@Entity(tableName = "users_fts")
data class UserFts(
    @PrimaryKey @ColumnInfo(name = "rowid") val id: Int,
    @ColumnInfo(name = "name") val name: String,
    @ColumnInfo(name = "email") val email: String
)

那么如何进行搜索呢?可以想象它和like关键字一样:

SELECT * FROM users_fts WHERE users_fts MATCH 'search term'

这里,需要重点讨论一下,MATCHLIKE的不同点:
sql1:

SELECT * FROM users WHERE name MATCH :searchQuery


sql2:

ELECT * FROM users WHERE name LIKE '%' || :searchQuery || '%'

对于 sql1:

  1. 这是全文搜索(Full-Text Search, FTS)查询。
  2. 使用 MATCH 操作符,它是专门为全文搜索设计的。
  3. 通常需要特殊的表设置,如在 SQLite 中使用 FTS3, FTS4 或 FTS5 虚拟表。
  4. 性能通常更好,特别是在大型数据集上。
  5. 支持更复杂的搜索查询,如词语搜索、近似匹配等。
  6. 可以根据相关性排序结果。
  7. 不支持通配符匹配。

对于 sql2:
  1. 这是一个标准的 SQL LIKE 查询。
  2. 使用 LIKE 操作符进行模式匹配。
  3. 可以在任何标准 SQL 表上使用,不需要特殊设置。
  4. 对于大型数据集,性能可能较差,特别是当使用前缀通配符 (‘%xxx’) 时。
  5. 支持简单的通配符匹配。
  6. 不提供内置的相关性排序。
  7. 更灵活,可以轻松进行部分匹配。

主要区别:

  1. 性能:
    MATCH 通常比 LIKE 更快,特别是在大型数据集上。LIKE 使用前缀通配符时无法使用索引,可能导致全表扫描。

  2. 功能
    MATCH 提供更强大的全文搜索功能,如词语搜索、相关性排序等。LIKE 则提供简单的模式匹配。

  3. 设置要求
    MATCH 需要特殊的表设置(FTS表),而 LIKE 可以在任何普通表上使用。

  4. 灵活性
    LIKE 在模式匹配方面更灵活,可以轻松进行部分匹配。MATCH 主要用于全词匹配或词语搜索

  5. 结果排序
    MATCH 可以基于相关性排序结果,LIKE 则不提供这种内置功能

  6. 语法
    MATCH 使用特定的搜索语法,而 LIKE 使用简单的通配符

使用建议:

  • 如果你需要高性能的全文搜索,特别是在大型数据集上,使用 MATCH。
  • 如果你需要简单的模式匹配,或者在小型数据集上工作,LIKE 可能就足够了。
  • 如果你不想或不能设置 FTS 表,那么就只能使用 LIKE。

在 Android Room 中如用 FTS:

@Fts4
@Entity(tableName = "users_fts")
data class UserFts(
    @PrimaryKey @ColumnInfo(name = "rowid") val id: Int,
    @ColumnInfo(name = "name") val name: String
)

@Dao
interface UserDao {
    @Query("SELECT * FROM users_fts WHERE name MATCH :query")
    fun searchUsers(query: String): List<UserFts>
}

可以观察到,Android Room 数据库中存在 @Fts4@Fts3注解,那么它们之间又有什么不同呢?

FTS3 和 FTS4 都是 SQLite 中的全文搜索扩展,但它们有一些重要的区别。了解这些差异可以帮助你选择最适合你的应用需求的版本。以下是 FTS3 和 FTS4 的主要区别:

  1. 性能:
    FTS4 通常比 FTS3 更快,特别是在插入和更新操作上。
    FTS4 在大型数据集上的查询性能也略优于 FTS3。

  2. 存储效率:
    FTS4 通常比 FTS3 更节省存储空间。
    FTS4 引入了压缩选项,可以进一步减少存储需求。

  3. 词干提取(Stemming):
    FTS4 支持内置的词干提取,而 FTS3 不支持。
    词干提取可以提高搜索的灵活性,例如搜索 “run” 也能匹配 “running”。

  4. 列名称:
    FTS3 使用默认的列名(content),而 FTS4 允许自定义列名。
    这使得 FTS4 在处理多列数据时更加灵活。

  5. 排序:
    FTS4 支持基于文档 ID 的结果排序,这在 FTS3 中是不可用的。
    术语近似度(Term Proximity):
    FTS4 提供了更好的术语近似度支持,允许更精确的短语搜索。

  6. Unicode 支持:
    FTS4 对 Unicode 的支持比 FTS3 更好,特别是在处理非 ASCII 字符时。

  7. 可选的前缀索引:
    FTS4 允许创建可选的前缀索引,这可以加速某些类型的查询,但会增加存储空间的使用。

  8. 向后兼容性:
    FTS4 向后兼容 FTS3,这意味着为 FTS3 编写的代码通常可以在 FTS4 上运行。

  9. 稳定性:
    FTS3 作为较早的版本,可能在某些旧版本的 SQLite 中更稳定。
    FTS4 在较新的 SQLite 版本中已经非常稳定。

使用建议:

  1. 对于大多数现代 Android 应用,FTS4 是更好的选择,因为它提供了更好的性能和更多的功能。
  2. 如果你的应用需要处理大量文本数据,或者需要高级搜索功能(如词干提取或更好的 Unicode 支持),FTS4 是明确的选择。
  3. 只有在你需要支持非常旧的 Android 版本,或者有特定的兼容性要求时,才应该考虑使用 FTS3。
  4. 如果你正在升级现有的使用 FTS3 的应用,迁移到 FTS4 通常是一个好主意,因为它提供了性能改进和额外的功能。
  5. 需要注意的是,Android 还支持 FTS5,它比 FTS4 更新,提供了更多的功能和性能改进。在新项目中,你可能想考虑直接使用 FTS5。
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐