你如何确定在 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
的其他查询的性能
我有一个问题,解决方法是交换先过滤的内容,但我不确定这是否可行,而且我对它的工作原理了解不够。
举个例子:
这是一个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
的其他查询的性能