4

在我的 PL/SQL 中有这个使用绑定变量的大动态 SQL。我使用 DBMS_SQL 包来绑定和执行生成的查询。

根据某些条件,将 where 子句添加到动态 SQL 中。当我只使用“in”或“=”来匹配我的绑定变量时,一切正常,并且返回结果非常快。

例子:

(servedparty = :bv_ or servedpartyimsi = :bv_)

但是,当我执行以下操作时:

(servedpartyimei like :bv_)

并提供像 12345679890% 这样的值,查询需要非常非常长的时间。

我也试过这样的东西

(servedpartyimei like :bv_||'%')

然后提供不带“%”的值,但结果相同

当我在没有绑定变量的情况下执行查询但只输入硬编码值时,结果也会立即返回。

我在这里做错了吗?不要像 LIKE 运算符那样绑定变量?有任何想法吗?

谢谢你。

4

3 回答 3

5

我认为您遇到了 Oracle 错误 9197434(使用 DBMS_SQL 时不会发生 BIND PEEKING)

据我所知,这还没有解决。

如果没有绑定变量窥视的好处,Oracle 不知道条件右侧的值是什么LIKE。例如,它可能只是“%”。因此,Oracle 假设有多少行将是LIKE一个典型的绑定变量值。这些假设非常保守,可能会迫使 Oracle 从您想要的快速计划(可能使用索引)转向您获得的慢速计划(可能使用散列连接)。

如果可能,我建议您使用 Native Dynamic SQL(即EXECUTE IMMEDIATE),因为它不会受到此错误的影响。否则,您可能需要提示您的 SQL。

于 2016-11-17T18:26:36.967 回答
4

当您将 LIKE 与绑定变量一起使用时,在某些旧版本中,Oracle 必须假设有多少行将匹配。我不记得它选择了什么值(它可能因版本而异)它可能是 5%、10% 等等。现在这可能与现实脱节并导致计划不佳。

有一个未记录的(且不受支持的)优化器参数调用_like_with_bind_as_equality,它的功能正如其名称所暗示的那样 - 即当设置true为时假定返回的行数与返回的行数column like :bv相同column = :bv。因此,如果您使用它,您可能会获得更快的计划。您可以通过设置它alter session

于 2016-11-17T18:23:56.007 回答
1

我遇到了同样的问题,我尝试了下面提到的,似乎工作正常

V_QUERY := V_QUERY||' AND FIRST_NAME LIKE ''%''||:VAR2||''%''';

谢谢

于 2020-04-04T12:54:13.997 回答