我有一个参数化的搜索查询并没有表现得太好,我认为这是因为参数嗅探。我想做this answer中提及的OPTION(RECOMPILE)
之类的事情,但我不确定Sybase的等价物是什么。
是否有Sybase等效的OPTION(RECOMPILE)
?或者我是否需要切换到存储过程才能获得该功能?
答案 0 :(得分:1)
注意:我不知道'参数嗅探'是什么,所以fwiw ......
我可以想象的几个场景(在我的脑海中)可以解释查询的糟糕性能,其中可以通过强制(重新)编译查询来提高性能:
1 - 表的DDL更改(例如,列数据类型更改,索引创建/修改)或更新的统计信息可能会导致更好的编译计划;在好日子里,有必要在这样的改变之后运行sp_recompile table_name
,但近年来(过去6到8年?)这应该在封面下自动执行; soooo,如果你正在运行一个(相对)旧版本的ASE,并假设对引用的表进行DDL / stats修改,那么在这样的DDL更改之后可能需要让表的所有者运行sp_recompile table-name
2 - 使用ASE 15/16,DBA配置启用了语句缓存的dataserver并不罕见;这允许数据服务器为不经常重复的查询创建轻量级过程(LWP;又称'temp'过程)(目标是消除代码相似查询的代价高昂的编译开销);使用语句缓存的缺点是参数值的差异可能导致记录计数的大的变化,这可能导致后续查询获得/重新使用与查询的先前副本相关联的“差”查询计划;在这种情况下,SQL开发人员可以在运行查询之前运行set statement_cache off
...这将覆盖数据服务器级别的任何语句缓存设置,并允许使用当前的SARG /参数集编译查询...需要权衡的是,您现在将承担编译提交给数据服务器的每个查询的开销
3 - 如果应用程序使用预准备语句提交“参数化”查询,则“准备”语句的过程通常会通知数据服务器创建LWP(也称为“临时”过程);在这种情况下,预编译语句的第一次调用将被编译并存储在过程高速缓存中,准备好的语句的后续调用(由应用程序)重新使用第一次调用的查询计划;同样,一个好处是消除了查询#2到#n的代价高昂的编译开销,但是如果参数值可能导致受影响的记录数量变化很大,则重新使用“差”查询计划的缺点;对于这种情况,我能想到的唯一“修复”是将应用程序重新编码为而不是使用预准备语句...并且如果数据服务器 配置了语句缓存启用后,确保在向数据服务器提交(未准备好)语句之前发出'set statement_cache off';当然,明显的缺点是每个查询现在都会产生编译的开销
注意:
set statement_cache {on|off}
是会话级设置;您只需要发出一次,为会话的其余部分启用(打开)或禁用(关闭)语句缓存
如果您知道有2(或3/4/5)个不同的参数集可能导致同一查询的不同优化计划,您可以通过提交相同的略有不同的版本来欺骗dataserver的语句缓存查找过程查询;对于dataserver,这些看起来像'不同'的查询,因此可以与语句缓存中的不同查询计划相匹配;使用这种小编码技术,您仍然可以使用语句缓存(或特定于应用程序的预准备语句),同时限制(消除?)重复使用“差”查询计划;例如,虽然这三个查询在逻辑上是相同的,但由于表别名不同,数据服务器会将它们视为“不同”的查询...
select count(*) from sysobjects where id = 1
select count(*) from sysobjects o where id = 1
select count(*) from sysobjects o1 where id = 1
...如果使用应用程序端预处理语句,那么您将创建/管理3个不同的预准备语句