ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 柱状图解析

柱状图解析

原创 Linux操作系统 作者:jcq0 时间:2009-11-02 13:40:26 0 删除 编辑

为了对数据分布不均匀的列产生更好的执行计划,我们可以搜集列的直方图信息,这些信息存放在相应的数据字典中,能够帮助CBO生成更为准确的执行计划。
直方图分为两种,一种是基于高度平衡的(Height-Balanced),一种是基于频率的(Frequency)。无论是哪种直方图都是以Bucket分割的。

当Bucket的个数大于等于distinct(列)时,Bucket存放的是一个值出现的次数,这时使用的是基于频率的直方图。

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0                                                                                                                                                        
Connected as test                                                                                                                                                                                                             
                                                                                                                                                                                                                              
SQL> select ID,COUNT(*) from test2 t GROUP BY ID order by id;                                                                                                                                                                 
                                                                                                                                                                                                                              
        ID   COUNT(*)                                                                                                                                                                                                         
---------- ----------                                                                                                                                                                                                         
         1          1                                                                                                                                                                                                         
         2          1                                                                                                                                                                                                         
         3          1                                                                                                                                                                                                         
         4          2                                                                                                                                                                                                         
         5          1                                                                                                                                                                                                         
         6          1                                                                                                                                                                                                         
         7          1                                                                                                                                                                                                         
         8          1                                                                                                                                                                                                         
         9         61                                                                                                                                                                                                         
        10          1                                                                                                                                                                                                         
                                                                                                                                                                                                                              
10 rows selected                                                                                                                                                                                                              
 
SQL> BEGIN                                                                                                                                                                                                                    
  2    DBMS_STATS.GATHER_table_STATS (OWNNAME => 'TEST', TABNAME => 'TEST2',                                                                                                                                                  
  3    METHOD_OPT => 'FOR COLUMNS SIZE 20 ID');                                                                                                                                                                               
  4  END;                                                                                                                                                                                                                     
  5  /                                                                                                                                                                                                                        
                                                                                                                                                                                                                              
PL/SQL procedure successfully completed                                                                                                                                                                                       
                                                                                                                                                                                                                              
SQL> select * from user_HISTOGRAMS where table_name='TEST2';                                                                                                                                                              
                                                                                                                                                                                                                              
TABLE_NAME    COLUMN_NAME    ENDPOINT_NUMBER ENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE  
------------- -------------- --------------- -------------- ------------------------
TEST2         ID                           1              1                        
TEST2         ID                           2              2                        
TEST2         ID                           3              3                        
TEST2         ID                           5              4                        
TEST2         ID                           6              5                        
TEST2         ID                           7              6                        
TEST2         ID                           8              7                        
TEST2         ID                           9              8                        
TEST2         ID                          70              9                        
TEST2         ID                          71             10                        
                                                                                                                                                                                                                              
10 rows selected                                                                                                                                                                                                              
                                                                                                                                                                                                                              
SQL>                                                                                                                                                                                                                          
SQL> select table_name,                                                                                                                                                                                                       
  2         column_name,                                                                                                                                                                                                      
  3         endpoint_number,                                                                                                                                                                                                  
  4         endpoint_number - lag(endpoint_number, 1, 0) over(order by endpoint_number),                                                                                                                                      
  5         endpoint_value                                                                                                                                                                                                    
  6    from user_histograms                                                                                                                                                                                                   
  7   where table_name = 'TEST2';                                                                                                                                                                                             
                                                                                                                                                                                                                              
TABLE_NAME    COLUMN_NAME   ENDPOINT_NUMBER ENDPOINT_NUMBER-LAG(ENDPOINT_N ENDPOINT_VALUE                                                 
------------- ------------- --------------- ------------------------------ --------------                                                 
TEST2         ID                          1                         1             1                                                 
TEST2         ID                          2                         1             2                                                 
TEST2         ID                          3                         1             3                                                 
TEST2         ID                          5                         2             4                                                 
TEST2         ID                          6                         1             5                                                 
TEST2         ID                          7                         1             6                                                 
TEST2         ID                          8                         1             7                                                 
TEST2         ID                          9                         1             8                                                 
TEST2         ID                         70                     61             9                                                 
TEST2         ID                         71                      1            10                                                  
                                                        
10 rows selected                                                                                                                                                                                                              
                                                                                                                                                                                                                              
SQL>  

当Bucket的个数小于distinct(列)时,Bucket无法存放单个值出现的次数,而是一个值的范围,在不同的Bucket的这个范围中所有的值的总数尽可能的均匀,这就是基于高度平衡的直方图。

                                                                                                                                                                                                                             
SQL>                                                                                                                                                                                                                          
SQL> BEGIN                                                                                                                                                                                                                    
  2    DBMS_STATS.GATHER_table_STATS (OWNNAME => 'TEST', TABNAME => 'TEST2',                                                                                                                              
  3    METHOD_OPT => 'FOR COLUMNS SIZE 5 ID');                                                                                                                                            4 END;                                                                                                                                    5  /                                                                                                                                                                                                                        
                                                                                                                                                                                                                              
PL/SQL procedure successfully completed                                                                                                                                                                                       
                                                                                                                                                                                                                              
SQL> select * from user_histograms where table_name='TEST2';                                                                                                                                                                  
                                                                                                                                                                                                                              
TABLE_NAME     COLUMN_NAME     ENDPOINT_NUMBER ENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE  
-------------- --------------- --------------- -------------- ------------------------
TEST2          ID                            0              1                        
TEST2          ID                            4              9                        
TEST2          ID                            5             10                        
                                                                                                                                                                                                                              
SQL>       
                                                                                                                                                                                                                   

此时1-8值段共有8条记录,9有61条记录,10有1条记录,Bucket只是尽最大的可能做到数据均匀。

在对数据不均匀的情况使用直方图时,如果系统未使用绑定变量,每次sql语句执行都需要硬解析,重新生成执行计划,这样得到的总是正确的执行计划。
如果使用绑定变量,那么就不需要硬解析,Oracle将总是使用第一次调用该语句时生成的执行计划(bind peeking),不幸的是在11g之前的版本都存在这个问题。
对于使用了绑定变量,搜集了直方图信息,又错走了执行计划的系统,真是一个噩梦!            

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/14130873/viewspace-617906/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-11-25

  • 博文量
    93
  • 访问量
    367947