楼主: eagle_fan

[精华] 对Hash Join的一次优化

[复制链接]
论坛徽章:
3
2011新春纪念徽章
日期:2011-02-18 11:43:34灰彻蛋
日期:2011-05-25 09:41:35ITPUB十周年纪念徽章
日期:2011-11-01 16:24:04
81#
发表于 2008-3-21 10:35 | 只看该作者
原帖由 eagle_fan 于 2008-3-21 10:29 发表


oracle通过hash函数生成值hash(col_name) ,然后根据hash(col_name)投放相应的bucket

所以col_name值相同肯定会在同一个bucket里面,col_name值不同也可能出现在一个bucket里面,因为当col_name number of distinct value > number of buckets是,难免会出现一个篮子里面有多个鸡蛋的情况



   觉得有点粗糙,能否发份官方文档?

使用道具 举报

回复
论坛徽章:
22
ITPUB元老
日期:2006-12-13 17:04:38ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41生肖徽章2007版:鼠
日期:2008-01-02 17:35:53生肖徽章2007版:虎
日期:2008-01-02 17:35:53生肖徽章2007版:兔
日期:2008-01-02 17:35:53生肖徽章2007版:猴
日期:2008-01-02 17:35:53生肖徽章2007版:鸡
日期:2008-01-02 17:35:53ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44会员2007贡献徽章
日期:2007-09-26 18:42:10授权会员
日期:2006-12-13 17:02:18
82#
发表于 2008-3-21 10:44 | 只看该作者
不错

使用道具 举报

回复
论坛徽章:
7
奥运会纪念徽章:皮划艇激流回旋
日期:2008-07-23 14:49:16生肖徽章2007版:兔
日期:2008-10-06 17:32:12奥运会纪念徽章:跳水
日期:2008-10-24 13:09:39生肖徽章2007版:兔
日期:2008-11-11 08:20:05生肖徽章2007版:龙
日期:2009-05-02 12:09:05生肖徽章2007版:狗
日期:2009-08-19 16:52:22祖国60周年纪念徽章
日期:2009-10-09 08:28:00
83#
发表于 2008-3-21 11:14 | 只看该作者
经典, ,我还有很多路要走啊!!!!!!!!!!!!!!!!!!!!!!

使用道具 举报

回复
论坛徽章:
2
授权会员
日期:2005-10-30 17:05:332011新春纪念徽章
日期:2011-02-18 11:43:36
84#
发表于 2008-3-21 12:01 | 只看该作者
刚刚做了几个实验,感觉hash table的建立并不是简单的根据hash key的值,
因为这个实验中,发现不同的hash key居然可以放在一个bucket中,

两张表,small_table 有1857条记录,big_table有418072条记录

SQL> select /*+leading(a) full(a) use_hash(a b)*/ count(b.q)
  2  from small_table a,big_table b
  3  where a.stcdt=b.stcdt;

COUNT(B.Q)
----------
    275340

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=551 Card=1 Bytes=15)
   1    0   SORT (AGGREGATE)
   2    1     HASH JOIN (Cost=551 Card=100336 Bytes=1505040)
   3    2       TABLE ACCESS (FULL) OF 'ST_RIVER_R' (Cost=188 Card=418072 Bytes=3762648)
   4    2       TABLE ACCESS (FULL) OF 'ST_STINFO_B' (Cost=5 Card=1857 Bytes=11142)

在这个实验中,hash key是一个primary key,是唯一值。
SQL> select count(*) from small_table;

  COUNT(*)
----------
      1857

SQL> select count(distinct stcdt) from small_table;

COUNT(DISTINCTSTCDT)
--------------------
                1857

如果按照lz的说法,每个bucket中是不是最多只有一条记录呢?

看看trace信息
############# 10104 trace info        #############

*** (continued) HASH JOIN BUILD HASH TABLE (PHASE 1) ***
### Hash table ###
# NOTE: The calculated number of rows in non-empty buckets may be smaller
#       than the true number.
Number of buckets with   0 rows:       2625
Number of buckets with   1 rows:       1152
Number of buckets with   2 rows:        260
Number of buckets with   3 rows:         51
Number of buckets with   4 rows:          8
Number of buckets with   5 rows:          0
Number of buckets with   6 rows:          0
Number of buckets with   7 rows:          0
Number of buckets with   8 rows:          0
Number of buckets with   9 rows:          0
Number of buckets with between  10 and  19 rows:          0
Number of buckets with between  20 and  29 rows:          0
Number of buckets with between  30 and  39 rows:          0
Number of buckets with between  40 and  49 rows:          0
Number of buckets with between  50 and  59 rows:          0
Number of buckets with between  60 and  69 rows:          0
Number of buckets with between  70 and  79 rows:          0
Number of buckets with between  80 and  89 rows:          0
Number of buckets with between  90 and  99 rows:          0
Number of buckets with 100 or more rows:          0
### Hash table overall statistics ###
Total buckets: 4096 Empty buckets: 2625 Non-empty buckets: 1471
Total number of rows: 1857
Maximum number of rows in a bucket: 4
Average number of rows in non-empty buckets: 1.262407

从trace信息中看到Maximum number of rows in a bucket: 4

使用道具 举报

回复
论坛徽章:
42
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:022011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:56管理团队成员
日期:2011-05-07 01:45:08ITPUB十周年纪念徽章
日期:2011-11-01 16:20:282012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:23
85#
发表于 2008-3-21 12:14 | 只看该作者
大家都学会dump了

使用道具 举报

回复
论坛徽章:
2
授权会员
日期:2005-10-30 17:05:332011新春纪念徽章
日期:2011-02-18 11:43:36
86#
发表于 2008-3-21 12:30 | 只看该作者
不知道oracle是通过什么算法对hash key进行散列的?
对不同的数据类型是使用不同的算法,还是有通用的算法?

使用道具 举报

回复
招聘 : Java研发
论坛徽章:
71
马上加薪
日期:2014-02-19 11:55:14蜘蛛蛋
日期:2012-12-26 18:16:01茶鸡蛋
日期:2012-11-16 08:12:48ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:07奥运会纪念徽章:网球
日期:2012-08-23 14:58:08奥运会纪念徽章:沙滩排球
日期:2012-07-19 17:28:14版主2段
日期:2012-07-07 02:21:02咸鸭蛋
日期:2012-03-23 18:17:482012新春纪念徽章
日期:2012-02-13 15:13:512012新春纪念徽章
日期:2012-02-13 15:13:51
87#
发表于 2008-3-21 12:49 | 只看该作者
原帖由 d.c.b.a 于 2008-3-21 12:14 发表
大家都学会dump了

不会呢还....

使用道具 举报

回复
论坛徽章:
27
授权会员
日期:2005-10-30 17:05:33管理团队成员
日期:2011-05-07 01:45:082012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:36优秀写手
日期:2013-12-18 09:29:13马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
88#
 楼主| 发表于 2008-3-21 12:52 | 只看该作者
原帖由 sharklove 于 2008-3-21 12:01 发表
刚刚做了几个实验,感觉hash table的建立并不是简单的根据hash key的值,
因为这个实验中,发现不同的hash key居然可以放在一个bucket中,

两张表,small_table 有1857条记录,big_table有418072条记录

SQL> select /*+leading(a) full(a) use_hash(a b)*/ count(b.q)
  2  from small_table a,big_table b
  3  where a.stcdt=b.stcdt;

COUNT(B.Q)
----------
    275340

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=551 Card=1 Bytes=15)
   1    0   SORT (AGGREGATE)
   2    1     HASH JOIN (Cost=551 Card=100336 Bytes=1505040)
   3    2       TABLE ACCESS (FULL) OF 'ST_RIVER_R' (Cost=188 Card=418072 Bytes=3762648)
   4    2       TABLE ACCESS (FULL) OF 'ST_STINFO_B' (Cost=5 Card=1857 Bytes=11142)

在这个实验中,hash key是一个primary key,是唯一值。
SQL> select count(*) from small_table;

  COUNT(*)
----------
      1857

SQL> select count(distinct stcdt) from small_table;

COUNT(DISTINCTSTCDT)
--------------------
                1857

如果按照lz的说法,每个bucket中是不是最多只有一条记录呢?

看看trace信息
############# 10104 trace info        #############

*** (continued) HASH JOIN BUILD HASH TABLE (PHASE 1) ***
### Hash table ###
# NOTE: The calculated number of rows in non-empty buckets may be smaller
#       than the true number.
Number of buckets with   0 rows:       2625
Number of buckets with   1 rows:       1152
Number of buckets with   2 rows:        260
Number of buckets with   3 rows:         51
Number of buckets with   4 rows:          8
Number of buckets with   5 rows:          0
Number of buckets with   6 rows:          0
Number of buckets with   7 rows:          0
Number of buckets with   8 rows:          0
Number of buckets with   9 rows:          0
Number of buckets with between  10 and  19 rows:          0
Number of buckets with between  20 and  29 rows:          0
Number of buckets with between  30 and  39 rows:          0
Number of buckets with between  40 and  49 rows:          0
Number of buckets with between  50 and  59 rows:          0
Number of buckets with between  60 and  69 rows:          0
Number of buckets with between  70 and  79 rows:          0
Number of buckets with between  80 and  89 rows:          0
Number of buckets with between  90 and  99 rows:          0
Number of buckets with 100 or more rows:          0
### Hash table overall statistics ###
Total buckets: 4096 Empty buckets: 2625 Non-empty buckets: 1471
Total number of rows: 1857
Maximum number of rows in a bucket: 4
Average number of rows in non-empty buckets: 1.262407

从trace信息中看到Maximum number of rows in a bucket: 4


你没看清我的回复啊:

“col_name值不同也可能出现在一个bucket里面,因为当col_name number of distinct value > number of buckets是,难免会出现一个篮子里面有多个鸡蛋的情况”

一个大集合到小集合的映射当然会出现N->1的情况

使用道具 举报

回复
论坛徽章:
3
授权会员
日期:2006-04-18 13:25:09生肖徽章2007版:猴
日期:2009-02-04 17:50:05ITPUB学员
日期:2011-08-03 10:55:36
89#
发表于 2008-3-21 13:40 | 只看该作者
原帖由 eagle_fan 于 2008-3-21 12:52 发表


你没看清我的回复啊:

“col_name值不同也可能出现在一个bucket里面,因为当col_name number of distinct value > number of buckets是,难免会出现一个篮子里面有多个鸡蛋的情况”

一个大集合到小集合的映射当然会出现N->1的情况


SQL> select count(distinct stcdt) from small_table;

COUNT(DISTINCTSTCDT)
--------------------
                1857


但是这里
col_name number of distinct value = 1857 而number of buckets是4096 按理说现在篮子多出来很多 但是还是出现了一个篮子装多个鸡蛋的情况 所以有些confused.

使用道具 举报

回复
论坛徽章:
2
授权会员
日期:2005-10-30 17:05:332011新春纪念徽章
日期:2011-02-18 11:43:36
90#
发表于 2008-3-21 13:49 | 只看该作者
原帖由 foreverlee 于 2008-3-21 13:40 发表


SQL> select count(distinct stcdt) from small_table;

COUNT(DISTINCTSTCDT)
--------------------
                1857


但是这里
col_name number of distinct value = 1857 而number of buckets是4096 按理说现在篮子多出来很多 但是还是出现了一个篮子装多个鸡蛋的情况 所以有些confused.



我想oracle的hash算法应该是某种类似mod()的算法,不同的值出现在一个bucket里很正常,但绝不是因为因为distinct值大于buckets数目时,才会把不同值放在一个bucket中

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表