MSQL优化基础(无直方图选择率)

案例一 无直方图  range 内 = 的选择率

选择率=1/NDV×非空率

非空率=(表行数-NUM_NULLS)/表行数

col column_name format a10;
col NUM_DISTINCT format 999;
col low_value format a10;
col high_value format a10;
col num_nulls format 999;
col HISTOGRAM format a10;

drop table test;
create table test(n1 number, c1 varchar2(20));
begin 
   for i in  1..100 loop
   if mod(i,9)=0 then
      insert into test values(null,null);
   else
      insert into test(n1,c1) values(i,i);
   end if;
   end loop;
   commit;
 end;
 /

exec dbms_stats.gather_table_stats(null,'test');
select column_name,num_distinct,low_value,high_value,num_nulls,HISTOGRAM  from user_tab_columns where table_name='TEST' and COLUMN_NAME='N1';

COLUMN_NAM NUM_DISTINCT LOW_VALUE  HIGH_VALUE NUM_NULLS HISTOGRAM
---------- ------------ ---------- ---------- --------- ----------
N1                   89 C102       C202              11 NONE

--以下SQL转换oracle内部结构看最大最小值
SQL> var b1 number;                                                                                                          
SQL> exec dbms_stats.convert_raw_value(hextoraw('&1'),:b1);                                                                  
Enter value for 1: C102                                                                                                      
PL/SQL procedure successfully completed.
SQL> print  b1;                                                                                                              
        B1
----------
         1

SQL> exec dbms_stats.convert_raw_value(hextoraw('&1'),:b1);                                                                  
Enter value for 1: C202                                                                                                     
PL/SQL procedure successfully completed.
SQL> print b1;                                                                                                               
        B1
----------
        100

COLUMN_NAM NUM_DISTINCT LOW_VALUE  HIGH_VALUE NUM_NULLS HISTOGRAM
---------- ------------ ---------- ---------- --------- ----------
N1                   89 C102(1)      C202(100)             11 NONE

		
表里边的总数:
SQL> select num_rows from user_tables where table_name='TEST';                                                               

  NUM_ROWS
----------
       100
	   

select * from test where n1=80;
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     5 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST |     1 |     5 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

选择率=1/NDV×非空率
非空率=(表行数-NUM_NULLS)/表行数

选择率= 1/89*(100-11)/100 = 0.01
基数:总行数*选择率=100×0.01=1

结论 基数和Rows都一样

 

案例二 无直方图  range 外  = 的选择率

selectivity(range内[=])/(2High-low-high)=x/(2high-low-绑定直)

select * from  test where N1=102;
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     5 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST |     1 |     5 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

selectivity(range内=)/(2High-low-high)=x/(2high-low-绑定直)
x=0.01*(2*100-1-102)/(2*100-1-100)=.00979798
基数=.00979798*100=.979798 =1  和rows一样 
如果 给定的值 >2high-low  或者 <2low-high   则给一个非常小的值

 

 

 

 

准备数据:

drop table t1;
create table t1(n1 number, c1 varchar2(20));
begin 
   for i in  1..2134 loop
   if mod(i,9)=0 then
      insert into t1 values(null,null);
   else
      insert into t1(n1,c1) values(trunc(dbms_random.value(1,98),0),dbms_random.string('U',20));
   end if;
   end loop
   commit;
 end;
 /
 
 
 收集数据
 exec dbms_stats.gather_table_stats(null,'t1');
 
 
 //查看数据分布
SQL> select column_name,num_distinct,low_value,high_value,num_nulls,HISTOGRAM  from user_tab_columns where table_name='T1' and COLUMN_NAME='N1';  
COLUMN_NAM NUM_DISTINCT LOW_VALUE  HIGH_VALUE NUM_NULLS HISTOGRAM
---------- ------------ ---------- ---------- --------- ----------
N1                   97 C102(1)       C162(97)             237 NONE

//总行数 
 SQL> select num_rows from user_tables where table_name='T1';                                                                 

  NUM_ROWS
----------
      2134

 


 

案例三  无直方图  range 内   > 的选择率

Selectivity=((high_value-当前绑定值)/(high_value-low_value))*非空率  

select * from t1 where n1>60;
非空率=(2134-237)/2134 = .888940956
Selectivity=(97-60)/(97-1)*.888940956 = .34261266
基数:总行数*选择率=2134*.34261266 =  731.135416
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |   731 | 15351 |     4   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |   731 | 15351 |     4   (0)| 00:00:01 |
--------------------------------------------------------------------------



案例四   无直方图  range 内   < 的选择率

Selectivity=((当前绑定值-low_value)/(high_value-low_value))*非空率 

 select * from  t1 where n1<20;
非空率=(2134-237)/2134 = .888940956
Selectivity=(20-1)/(97-1)*.888940956 =  .175936231
基数:总行数*选择率=2134*.175936231 =   375.447917
 --------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |   375 |  7875 |    15   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |   375 |  7875 |    15   (0)| 00:00:01 |
--------------------------------------------------------------------------

 

 

案例五   无直方图 >= (in-Range) 选择率

 Selectivity=((high_value-当前绑定值)/(high_value-low_value)+1/ndv)*非空率

select * from  t1 where n1<=20; 
非空率=(2134-237)/2134 = .888940956
Selectivity=((20-1)/(97-1)+1/97)*.888940956 =  .185100571
基数:总行数*选择率=2134*.185100571 =   395.004619
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |   395 |  8295 |    15   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |   395 |  8295 |    15   (0)| 00:00:01 |
--------------------------------------------------------------------------


实例六  between (in-Range) 选择率

Selectivity=((valu1-value2)/(high_value-low_value)+2*1/ndv)*非空率 

select * from  t1 where n1 between 20 and 50;
非空率=(2134-237)/2134 = .888940956
Selectivity=((50-20)/(97-1)+2*1/97)*.888940956 =  .296122728
基数:总行数*选择率=2134*.296122728 = 631.925902
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |   632 | 13272 |     4   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |   632 | 13272 |     4   (0)| 00:00:01 |
--------------------------------------------------------------------------


 

案例七 > (out-of-Range) 选择率

转换成 =  (out-of-range) 来处理

=  (out-of-range) 来处理 的公式 
selectivity/(2High-low-high)=x/(2high-low-绑定直)
其中 selectivity=1/div*非空率

explain plan for select * from t1 where n1>150;    这两句的结果是一样的
select * from table(dbms_xplan.display);
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     9 |   189 |     4   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |     9 |   189 |     4   (0)| 00:00:01 |
--------------------------------------------------------------------------

explain plan for select * from t1 where n1=150;    这两句的结果是一样的
select * from table(dbms_xplan.display);
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     9 |   189 |     4   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |     9 |   189 |     4   (0)| 00:00:01 |
--------------------------------------------------------------------------

=  (out-of-range) 来处理 的公式  
selectivity/(2High-low-high)=x/(2high-low-绑定直)
其中 selectivity=1/div*非空率
1/97×(2134-237)/2134/(2*97-1-97)*(2*97-1-150)  =.004104861
基数=.004104861*2134= 8.75977337
特殊情况 如果  绑定值 远远大于 97(最大值) 则 rows =1


 

实例八 < (out-of-Range) 选择率

< (out-of-Range) 选择率

<span style="background-color: rgb(153, 255, 255);">a.   涵盖整个表 , n1< b , b>max_value
</span>explain plan for select * from t1 where n1<300;
select * from table(dbms_xplan.display);
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  1897 | 39837 |    15   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |  1897 | 39837 |    15   (0)| 00:00:01 |
--------------------------------------------------------------------------
返回: all_rows-nuu_rows = 2134-237 =  1897 

b.   比 最小值还小   转换成  out-of-range =  的情况
 
<font style=""><span style=""><span style="background-color: rgb(102, 204, 204);"><span style="color:#99ffff;"> x/(绑定值 -(2low-high))= selectivity/(low-(2low-high))</span>
</span></span></font> x=selectivity/(low-(2low-high))*(绑定值 -(2low-high))
  =(1/97)*(2134-237)/2134/(1-(2*1-97))*(-1-(2*1-97))=0.00897341600724001
cardinality=  0.00897341600724001*2134=19.1492697594502
explain plan for select * from t1 where n1<-1;
select * from table(dbms_xplan.display);
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    19 |   399 |     4   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |    19 |   399 |     4   (0)| 00:00:01 |
--------------------------------------------------------------------------

<span style="background-color: rgb(102, 204, 204);">c. 比  2low -high 还小  则会给一个非常小的值  
</span>select * from t1 where n1<-200;
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    21 |     4   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |     1 |    21 |     4   (0)| 00:00:01 |
--------------------------------------------------------------------------


 

案例九扩张

between 扩展   60 到 200    一边超出了 其实 下边这两句等效
select * from t1 where n1 >=60;
select * from t1  where n1 between 60 and 200;



NOT A  选择率
1-A 的选择率


COL is NULL
num_nulls/num_rows

col is not null
1- COL is NULL


 

补充 10053

alter session set evnet '10053 trace name context forever , level 1'
select * from t1 where n1=80;
alter session set evnet '10053 trace name context off'

打开10053
搜: Best::
 

nestloop 的内层循环的a-row 是 外层数乘出来的

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值