6

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

create index acadress_codpost_lower on acadress(LOWER(l5_codpost))

然后我运行一个使用索引的复杂查询。没有索引需要 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

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

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

4

1 回答 1

1

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

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

"where LOWER(aca.l5_codpost) like '"+StringEscapeUtils.escapeSql("NG179GT".toLowerCase())+"'"

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

另一方面,如果我有:

where LOWER(aca.l5_codpost) like :postcode

query.setString("postcode", "NG179GT".toLowerCase());

然后它不使用索引。

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

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

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

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

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

于 2015-02-04T11:08:41.943 回答