如何在查询中确定基数?

Rad*_*hiu 2 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%';
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

第一个查询具有以下说明计划:

--------------------------------------------------------------------------------
| 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%')
Run Code Online (Sandbox Code Playgroud)

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

--------------------------------------------------------------------------------
| 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 )
Run Code Online (Sandbox Code Playgroud)

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

我的假设是,该基数是每个条件(如果分别评估每个条件,并且所有这些均基于表统计信息)将返回的最大行数。这就是为什么在我的第一个查询中,假定的最大值为65,因为WHERE条件稍宽一些。

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

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

预先感谢您的任何帮助

Hus*_*vik 5

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

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

所以你

LIKE示例大约(5 % + 5 % - (5 % * 5 %)) * 95 % * 95 % => 8.8 %是表总行数。 - (5 % * 5 %)是因为OR运算符的交集。

REGEX例如1 % * 5 % => 0.05 %表总数。

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