您的位置:首页 > 数据库

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

2015-07-01 15:43 337 查看

案例一 无直方图 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 是 外层数乘出来的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: