楼主: eagle_fan

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

[复制链接]
论坛徽章:
59
狮子座
日期:2016-03-26 13:35:402013年新春福章
日期:2013-02-25 14:51:24双黄蛋
日期:2013-02-25 11:06:15ITPUB 11周年纪念徽章
日期:2012-10-09 18:06:20灰彻蛋
日期:2012-04-25 13:19:33紫蛋头
日期:2012-03-14 11:16:09最佳人气徽章
日期:2012-03-13 17:39:18玉石琵琶
日期:2012-02-21 15:04:38鲜花蛋
日期:2011-11-30 14:13:01ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15
91#
发表于 2008-3-21 13:51 | 只看该作者
不会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
92#
 楼主| 发表于 2008-3-21 13:59 | 只看该作者
原帖由 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 函数

使用道具 举报

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



根据sharklove实验的推想:
在这个实验中,hash key是一个primary key,是唯一值。
所有build_table中的hash colum经过某一个hash function处理后

分类讨论:
1 得到的Hash value应该是唯一的(hash key是一个primary key).又由于这里column of distinct value < hash bucket number

所以按道理每个hash bucket只应当对应一个row 但实际上Oracle 并不是这样.
Maximum number of rows in a bucket: 4


2 如果Oracle 取mod()类似的可循环性函数作为hash function做 rows与hash buckets的对应关系
那么 每个hash bucket得到的row数量应该是相等的
但这里可以发现很不均匀.
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


所以我觉得Oracle的Hash Function不能单单用
select count(*),col1_name,col2_name,...colN_name from build_table
group by col1_name,col2_name....colN_name去准确描述. 但如果只是找规律 应该可以采用.

使用道具 举报

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


并不是篮子比鸡蛋多就一定是一个篮子里面只有一个鸡蛋,我只是说如果鸡蛋比篮子多,那么肯定有一个篮子里面多于一个鸡蛋

当鸡蛋比篮子数目少时,也会出现一个篮子里面有多个鸡蛋的情况,因为有些篮子是空的,这取决于你的数据内容和oracle hash 函数


由于他primary key所以数据内容是唯一的 所以这里感觉上Oracle在处理Hash Join所采用的Hash Function比较具有决定性 in terms of data mapping between build_table rows and hash buckets.


ps. All of sudden, I am not able to type Chinese.

使用道具 举报

回复
论坛徽章:
129
蓝锆石
日期:2008-08-23 16:25:58萤石
日期:2008-02-26 15:38:51祖母绿
日期:2008-08-18 16:12:54海蓝宝石
日期:2008-02-23 15:06:23紫水晶
日期:2008-08-22 14:58:26红宝石
日期:2008-07-26 15:02:37九尾狐狸
日期:2008-09-16 09:24:50红孩儿
日期:2008-10-26 12:20:09紫蜘蛛
日期:2008-11-19 08:33:41玉兔
日期:2009-02-02 09:09:53
95#
发表于 2008-3-21 17:33 | 只看该作者
学了点东西,不过,我会SQL优化还是很不懂,先收藏下,再好好研究研究。

使用道具 举报

回复
论坛徽章:
0
96#
发表于 2008-3-22 10:30 | 只看该作者
无能不顶~

使用道具 举报

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




2 如果Oracle 取mod()类似的可循环性函数作为hash function做 rows与hash buckets的对应关系
那么 每个hash bucket得到的row数量应该是相等的
但这里可以发现很不均匀.
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


所以我觉得Oracle的Hash Function不能单单用
select count(*),col1_name,col2_name,...colN_name from build_table
group by col1_name,col2_name....colN_name去准确描述. 但如果只是找规律 应该可以采用.


用mod()之类的函数生成hash值只是在理论上(或者说总的概率上)每个bucket的row数量相等,
但实际情况还是要看hash key值的具体分布情况,
举个例子:
假设oracle的hash function是对10取余:mod(x,10)
对下列数据做散列,
1,
11,
21,
31,
41,
51,
61
你会发现即便每个数据都是唯一值,结果这些数最后都装到一个bucket里了。

这个问题要好好研究下。

使用道具 举报

回复
论坛徽章:
2
参与2007年甲骨文全球大会(中国上海)纪念
日期:2007-08-06 15:19:01ITPUB社区12周年站庆徽章
日期:2013-10-08 14:59:19
98#
发表于 2008-4-18 16:27 | 只看该作者
谢谢分享,分析非常透彻

使用道具 举报

回复
论坛徽章:
273
生肖徽章2007版:猪
日期:2008-09-27 09:35:45明尼苏达森林狼
日期:2009-01-12 14:15:09生肖徽章2007版:猪
日期:2009-01-21 16:30:59布鲁克林篮网
日期:2009-03-03 14:42:32圣安东尼奥马刺
日期:2009-03-03 14:44:41生肖徽章2007版:鸡
日期:2009-03-03 21:45:52生肖徽章2007版:牛
日期:2009-03-09 14:03:42生肖徽章2007版:猪
日期:2009-03-10 21:37:00生肖徽章2007版:羊
日期:2009-03-16 10:17:11生肖徽章2007版:虎
日期:2009-03-24 21:26:52
99#
发表于 2008-4-21 20:02 | 只看该作者
好东西
慢慢学习

使用道具 举报

回复
论坛徽章:
168
马上加薪
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-01-04 11:49:54蜘蛛蛋
日期:2011-12-05 16:08:56ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41设计板块每日发贴之星
日期:2011-07-22 01:01:02ITPUB官方微博粉丝徽章
日期:2011-06-30 12:30:16管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:33
100#
发表于 2008-5-8 09:59 | 只看该作者
marked

使用道具 举报

回复

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

本版积分规则 发表回复

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