在 sqlite 中,`regexp`(需手动启用)与 `like '%word%'` 均可用于子串模糊匹配,但二者底层机制不同:`like '%word%'` 无法利用 b-tree 索引加速通配符前缀查询,而 `regexp` 默认完全不走索引;实测表明,**两者性能相近且普遍较慢,均不适合高频、大数据量的 `%word%` 全文模糊搜索**。
mattn/go-sqlite3 是 Go 语言中广泛使用的 SQLite 绑定库,它支持通过编译选项(如 -tags sqlite_regexp)或运行时注册自定义函数来启用 REGEXP。但需明确:SQLite 原生并不内置 REGEXP 运算符——它只是一个可选的扩展函数,其行为和性能完全取决于你提供的正则实现(例如基于 re2 或 regexp/syntax 的 Go 回调)。
以 LIKE '%word%' 为例,该模式因左侧通配符 % 导致 SQLite 无法使用索引进行范围跳转,必须执行全表扫描(full table scan),时间复杂度为 O(N×M)(N 为行数,M 为平均字符串长度)。而 REGEXP 'word'(无锚点)同样无法利用索引,且额外引入正则引擎的编译与匹配开销,在多数场景下实际性能略逊于 LIKE。
你可以参考 mattn/go-sqlite3 项目中的基准测试框架自行验证。例如,修改其 sqltest.go 中的 BenchmarkRows,添加对比逻辑:
func BenchmarkLikeSearch(b *testing.B) {
db.once.Do(makeBench)
for i := 0; i < b.N; i++ {
rows, err := db.Query("SELECT id FROM bench WHERE name LIKE ?", "%sqlite%")
if err != nil {
b.Fatal(err)
}
rows.Close()
}
}
func BenchmarkRegexpSearch(b *testing.B) {
db.once.Do(makeBench)
// 确保已注册 regexp 函数(例如 via sqlite3.RegisterFunc)
for i := 0; i < b.N; i++ {
rows, err := db.Query("SELECT id FROM bench WHERE name REGEXP ?", "sqlite")
if err != nil {
b.Fatal(err)
}
rows.Close()
}
}⚠️ 注意事项:

总之,不要寄希望于 REGEXP 替代 LIKE 来提升 %word% 性能——它们本质都是线性扫描。真正的优化应从数据模型和检索架构入手。