在 `LIKE :varname || 上使用索引火鸟中的“%”

Using index on `LIKE :varname || '%'` in firebird

我有一个问题

SELECT DISTINCT FKDOCUMENT
FROM PNTM_DOCUMENTS_FT_INDEX
WHERE WORD LIKE 'sometext%'

PLAN SORT ((PNTM_DOCUMENTS_FT_INDEX INDEX (IX_PNTM_DOCUMENTS_FT_INDEX)))

它工作正常。

但是当我尝试将连接字符串与 LIKE 一起使用时,firebird 不使用索引 :

SELECT DISTINCT FKDOCUMENT
FROM PNTM_DOCUMENTS_FT_INDEX
WHERE WORD LIKE 'sometext' || '%'

PLAN SORT ((PNTM_DOCUMENTS_FT_INDEX NATURAL))

如何强制使用索引?

简短的回答,正如我已经评论过的那样,如果您不需要类似的模式,但总是想进行前缀搜索,则使用 STARTING [WITH] 而不是 LIKE。所以:

WHERE WORD STARTING WITH 'sometext' -- No %!

WHERE WORD STARTING WITH :param

据我所知,这正是 Firebird 使用 LIKE 'sometext%' 所做的。这将在可用时使用索引,并且您无需为存在类似模式符号而将其转义。缺点是不能使用 like 模式符号。

现在关于为什么当你使用

时 Firebird 不使用索引
WHERE WORD LIKE :param || '%' -- (or LIKE :param) for that matter

WHERE WORD LIKE 'sometext' || '%'

第一种情况很容易解释:语句准备与执行分开进行。 Firebird 需要考虑参数值以 _ 或 - 更糟 - % 开头的可能性,并且它不能为此使用索引。

至于第二种情况,应该可以将其优化为 LIKE 'sometext%' 的等价物,但 Firebird 可能认为任何不是普通文字的东西都不可优化。对于这个具体的例子,有可能决定它应该是可优化的,但这是一个非常具体的例外(通常不会像这样连接文字,大多数时候一个或多个 'black' 框,如列,函数,涉及案例陈述等)。