为什么Sybase不使用功能索引?

Tim*_*m B 6 java sybase prepared-statement functional-index

我在sybase表上创建了一个功能索引.

create index acadress_codpost_lower on acadress(LOWER(l5_codpost))
Run Code Online (Sandbox Code Playgroud)

然后我运行一个使用索引的复杂查询.没有索引需要17.086秒.索引需要0.076秒.

我从两个不同的SQL客户端以及开发和预生成的Sybase服务器上运行它.在所有情况下,我都看到了索引的加速度.

但是当我们从Java运行一个相同的查询时(我知道它是相同的,因为我已经记录了生成的SQL并直接在SQL客户端中使用它),那么性能与我们添加索引之前完全相同.

从ACE和SQuirreL运行而不是从Java运行时,相同的SQL查询可能有什么原因可以使用索引?

我的第一个想法是,Sybase可能正在缓存Prepared Statements的执行计划,而不是使用索引.我们已经尝试多次重启Java服务器(其他服务使用Sybase服务器因此更难反弹)并且没有任何区别.

另一种可能性是我们使用的是非常旧版本的Sybase驱动程序:

jConnect (TM) for JDBC(TM)/7.00(Build 26502)/P/EBF17993/JDK16/Thu Jun 3 3:09:09 2010
Run Code Online (Sandbox Code Playgroud)

此版本的JConnect可能不支持功能索引吗?

有谁知道这些理论中的任何一个是否正确,或者是否还有其他我错过的东西?

Tim*_*m B 1

在过去的一周左右的时间里,我一直在断断续续地研究这个问题,虽然我仍然没有明确的答案,但我确实有一个合理的理论。

我尝试了评论中的建议,感谢他们,如果我有疑问,我能够将原因缩小到一个更改:

"where LOWER(aca.l5_codpost) like '"+StringEscapeUtils.escapeSql("NG179GT".toLowerCase())+"'"
Run Code Online (Sandbox Code Playgroud)

然后查询使用索引并且返回速度极快。

另一方面,如果我有:

where LOWER(aca.l5_codpost) like :postcode

query.setString("postcode", "NG179GT".toLowerCase());
Run Code Online (Sandbox Code Playgroud)

那么它不使用索引。

理论上,Sybase 正在优化查询计划,但没有有关 内容的信息:postcode,因此它没有使用索引。一旦知道内容,它就不会重新编译查询,因此它永远不会使用索引。

我尝试过强制使用索引(index acadress_codpost_lower),但这没有什么区别。

我已经尝试过set forceplan offset literal_autoparam off但都没有任何区别。

我能发现改变行为的唯一方法是将选项直接嵌入到查询计划中,而不是将其作为参数。

因此,解决方法是将参数嵌入到查询字符串中,尽管我仍然想知道实际发生的情况并正确解决问题。