你如何确定在 Oracle 中首先过滤什么 where 子句以及如何控制它

How do you identify what where clause will be filtered first in Oracle and how to control it

我有一个问题,解决方法是交换先过滤的内容,但我不确定这是否可行,而且我对它的工作原理了解不够。

举个例子:

这是一个table

当您使用 ff 查询过滤时:

select * from pcparts where Parts = 'Monitor' and id = 255322 and Brand = 'Asus'

根据逻辑,这将是正确的,因为在其 ID 中包含字符的 Asus 组件将被过滤并防止 ORA-01722 错误。

但根据我的经验,这是不一致的。

我尝试在两个不同的数据库连接中使用相同的过滤,第一个没有得到错误(如预期的那样)但另一个得到了 ORA-01722 错误。

检查解释计划,两个数据库的区别在于 ff:

我在想是否可以确保在 ID 之前先过滤部件,但我在搜索时找不到任何东西,这是否可能,如果不能,请问有什么解决办法不依赖使用 TO_CHAR

的问题

“修复”相当简单:控制您正在做的事情。

显然 ID 列的数据类型是 VARCHAR2。因此,不要让 Oracle 猜测,而是指示它做什么。

No : select * from pcparts where Parts = 'Monitor' and id =  255322  and Brand = 'Asus'
Yes: select * from pcparts where Parts = 'Monitor' and id = '255322' and Brand = 'Asus'  
                                                            --------
                                 VARCHAR2 column's value enclosed into single quotes

我假设您想(在某种程度上)修复有问题的程序而不更改源代码。

根据您的图片,您正在使用“过滤谓词”,这通常意味着 Oracle 没有使用索引(虽然我不知道是什么以这种方式显示执行计划)。

如果您在 PARTS 上有一个索引,Oracle 可能会使用这个索引。

create index myindex on mytable (parts);

如果Oracle认为这个索引效率低下,它可能仍会使用全table扫描。您可以尝试 'fake' Oracle 通过谎报不同值的数量(不同值越多,效率越高)来认为这是一个有效的索引

exec dbms_stats.set_index_stats(ownname => 'myname', indname => 'myindex', numdist => 100000000)

注意:这将影响使用此 table

的其他查询的性能