oracle - 查询中的基数是如何确定的?

标签 oracle oracle11g

我有两个查询返回相同的结果集,但在检查执行计划时它们具有不同的基数值。

查询是:

select acq_cod
    , prp
    , df_val
    , descr
from acqdefprp
where (prp like '%pswd%' or prp like '%Pswd%')
    and prp not like '%kno%'
    and prp not like '%encr%';

select acq_cod
       , prp
       , df_val
       , descr
from acqdefprp
where regexp_instr(prp, 'pswd', 1,1,0,'i' ) > 0
    and regexp_instr(prp, '(encr)|(kno)', 1,1,0,'i' ) = 0;

第一个查询具有以下解释计划:

--------------------------------------------------------------------------------
| Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |            |    65 |  4485 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| acqdefprp  |    65 |  4485 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(("PRP" LIKE '%pswd%' OR "PRP" LIKE '%Pswd%') 
           AND "PRP" NOT LIKE '%kno%' 
           AND "PRP" NOT LIKE '%encr%')

第二个查询的解释计划是:

--------------------------------------------------------------------------------
| Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |            |    1  |    69 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| acqdefprp  |    1  |    69 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------------

   1 - filter(REGEXP_INSTR ("PRP",'(encr)|(kno)',1,1,0,'i') = 0
           AND REGEXP_INSTR ("PRP",'pswd',1,1,0,'i') > 0 )

我的问题是为什么两个执行计划之间的基数不同?对于第一个计划,基数(行)是 65,第二个计划是 1?

我的假设是,如果单独评估每个条件,则此基数是每个条件将返回的最大行数,并且所有这些都基于表统计信息。这就是为什么我的第一个查询假定最大值为 65,因为 WHERE 条件稍微宽松一些。

这也是为什么第二个查询的基数为 1,因为 regexp_instr 的限制性更强。

如果我的假设不正确,我真的很想知道是什么决定了这个基数。

预先感谢您的帮助

最佳答案

在您的情况下,表达式太复杂,优化器无法使用基本统计数据来估计基数。在这些情况下(您似乎没有使用可能影响 LIKE 谓词的直方图),使用固定选择性:

等号运算符:1% 不等式运算符:5%

所以你的

LIKE 示例大约占表格总行数的 (5 % + 5 % - (5 % * 5 %)) * 95 % * 95 % => 8.8 %- (5 % * 5 %) 是由于 OR 运算符而产生的交集。

REGEX 示例是表总行数的 1 % * 5 % => 0.05 %

Oracle 还支持扩展统计信息,您可以在其中计算特定表达式或相关列的统计信息和直方图。

关于oracle - 查询中的基数是如何确定的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33611207/

相关文章:

SQL 选择表 1 或表 2

sql - 甲骨文-ORA-01489 : result of string concatenation is too long

oracle - cfqueryparam 表现得很奇怪

java - oracle 11g以及hibernate spring和jsf的集成

sql - 从表中的对值中获取计数

oracle - 如何检查Oracle 11g中是否存在序列?

java - 在 Oracle PL/SQL 中调用存储过程

oracle - 如何在选择语句中检索到的值的结尾和开头添加单引号

sql - 更改 Oracle 11gR2 的 WM_CONCAT 函数的分隔符

oracle11g - 甲骨文 : Replacing non-numeric chars in a string