楼主: eagle_fan

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

[复制链接]
论坛徽章:
14
会员2007贡献徽章
日期:2007-09-26 18:42:10生肖徽章2007版:鸡
日期:2009-10-29 16:15:30生肖徽章2007版:兔
日期:2009-04-14 19:32:34生肖徽章2007版:猴
日期:2008-11-28 10:39:32奥运会纪念徽章:摔跤
日期:2008-08-12 10:59:32奥运会纪念徽章:艺术体操
日期:2008-08-07 09:43:42奥运会纪念徽章:举重
日期:2008-05-04 17:12:35生肖徽章2007版:鼠
日期:2008-01-02 17:35:53生肖徽章2007版:牛
日期:2008-01-02 17:35:53生肖徽章2007版:虎
日期:2008-01-02 17:35:53
11#
发表于 2008-3-17 13:56 | 只看该作者
不错学习了

使用道具 举报

回复
论坛徽章:
13
数据库板块每日发贴之星
日期:2007-09-20 01:04:22铁扇公主
日期:2012-02-21 15:02:402010新春纪念徽章
日期:2010-03-01 11:08:28月度精华徽章
日期:2009-04-01 02:15:18数据库板块每日发贴之星
日期:2008-05-17 01:02:08生肖徽章2007版:兔
日期:2008-04-07 19:49:48生肖徽章2007版:鼠
日期:2008-01-02 17:35:53生肖徽章2007版:鸡
日期:2008-01-02 17:35:53ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44数据库板块每日发贴之星
日期:2007-10-20 01:03:31
12#
发表于 2008-3-17 13:57 | 只看该作者
为什么在bigtable上不建立索引呢?

使用道具 举报

回复
论坛徽章:
14
会员2007贡献徽章
日期:2007-09-26 18:42:10生肖徽章2007版:鸡
日期:2009-10-29 16:15:30生肖徽章2007版:兔
日期:2009-04-14 19:32:34生肖徽章2007版:猴
日期:2008-11-28 10:39:32奥运会纪念徽章:摔跤
日期:2008-08-12 10:59:32奥运会纪念徽章:艺术体操
日期:2008-08-07 09:43:42奥运会纪念徽章:举重
日期:2008-05-04 17:12:35生肖徽章2007版:鼠
日期:2008-01-02 17:35:53生肖徽章2007版:牛
日期:2008-01-02 17:35:53生肖徽章2007版:虎
日期:2008-01-02 17:35:53
13#
发表于 2008-3-17 14:00 | 只看该作者
原帖由 rollingpig 于 2008-3-17 13:24 发表
这样如何?

select /*+ leading(b) use_hash(a b) */ distinct a.ID
from BIG_TABLE a, SMALL_TABLE b
where (a.category||' '||a.site_id  = b.from_cat||' '||b.site_id
   or a.category2||' '||a.site_id  = b.from_cat||' '||b.site_id
) and a.sale_end >= sysdate;



lz这个sql使用了么?结果如何?

使用道具 举报

回复
论坛徽章:
68
2015年新春福章
日期:2015-03-06 11:57:31奥运会纪念徽章:手球
日期:2012-09-13 15:50:49奥运会纪念徽章:水球
日期:2012-08-26 20:46:49版主1段
日期:2012-05-15 15:24:112012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-01-04 11:49:54
14#
发表于 2008-3-17 14:04 | 只看该作者
good article, and 好熟悉的table name

使用道具 举报

回复
论坛徽章:
76
双子座
日期:2015-07-28 14:26:072012新春纪念徽章
日期:2012-02-13 15:09:52ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15鲜花蛋
日期:2011-08-26 02:02:24管理团队成员
日期:2011-05-07 01:45:082010广州亚运会纪念徽章:皮划艇
日期:2011-04-18 11:24:412011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:15
15#
发表于 2008-3-17 14:15 | 只看该作者
学习下

使用道具 举报

回复
论坛徽章:
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
16#
 楼主| 发表于 2008-3-17 14:20 | 只看该作者
原帖由 gengyonghui 于 2008-3-17 13:08 发表
select /*+ leading(b) use_hash(a b) */ distinct a.ID
from BIG_TABLE a, SMALL_TABLE b
where (a.category  = b.from_cat or
       a.category2 = b.from_cat) and
       a.site_id  = b.site_id and
       a.sale_end >= sysdate;


两点建议:

1.查看sale_end列,看是否有必要建索引。
2.改写成
select a.ID
from BIG_TABLE a
where a.sale_end >= sysdate
and exists(select null
             from  SMALL_TABLE b
            where a.site_id  = b.site_id
              and b.from_cat in(a.category,a.category2)
           )


忘记说明了,sale_end >= sysdate返回大量的数据,不适合走索引,自然也不适合走Nest Loop

[ 本帖最后由 eagle_fan 于 2008-3-17 14:37 编辑 ]

使用道具 举报

回复
论坛徽章:
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
17#
 楼主| 发表于 2008-3-17 14:21 | 只看该作者
原帖由 netbanker 于 2008-3-17 14:04 发表
good article, and 好熟悉的table name


原来的表名被我匿了,取了个通用的表名

使用道具 举报

回复
论坛徽章:
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
18#
发表于 2008-3-17 14:26 | 只看该作者
从Access & Filter这儿看不出东东?

使用道具 举报

回复
论坛徽章:
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
19#
 楼主| 发表于 2008-3-17 14:29 | 只看该作者
原帖由 rollingpig 于 2008-3-17 13:24 发表
这样如何?

select /*+ leading(b) use_hash(a b) */ distinct a.ID
from BIG_TABLE a, SMALL_TABLE b
where (a.category||' '||a.site_id  = b.from_cat||' '||b.site_id
   or a.category2||' '||a.site_id  = b.from_cat||' '||b.site_id
) and a.sale_end >= sysdate;


这是你的SQL的PLAN,个人感觉上没有用Union自然
[PHP]
--------------------------------------------------------------------------
| Id  | Operation            |  Name        | Rows  | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |              |    81 |  7047 |    34  (12)|
|   1 |  SORT UNIQUE         |              |    81 |  7047 |    34  (12)|
|   2 |   CONCATENATION      |              |       |       |            |
|*  3 |    HASH JOIN         |              |     4 |   348 |    17  (12)|
|   4 |     TABLE ACCESS FULL| SMALL_TABLE  |  1879 | 48854 |    14   (8)|
|*  5 |     TABLE ACCESS FULL| BIG_TABLE    |     4 |   244 |     3  (34)|
|*  6 |    HASH JOIN         |              |     4 |   348 |    17  (12)|
|   7 |     TABLE ACCESS FULL| SMALL_TABLE  |  1879 | 48854 |    14   (8)|
|*  8 |     TABLE ACCESS FULL| BIG_TABLE    |     4 |   244 |     3  (34)|
--------------------------------------------------------------------------
[/PHP]

我们在tuning sql的时候可以站在oracle的角度想问题

起初我认为oracle应该更加smart一点,可以通过small_table(from_cat,site_id)来建立build table,然后在probe big_table的时候计算出两个hash值,第一个值基于(category, site_id),第二个值基于(category2,site_id)然后根据这两个hash值选择相应的bucket做链表扫描,这样的话FTS只需要一次

可惜oracle让我失望了,并没有如我一般的smart ,所以两次FTS无法避免

使用道具 举报

回复
论坛徽章:
3
2011新春纪念徽章
日期:2011-02-18 11:43:34灰彻蛋
日期:2011-05-25 09:41:35ITPUB十周年纪念徽章
日期:2011-11-01 16:24:04
20#
发表于 2008-3-17 14:30 | 只看该作者
原帖由 eagle_fan 于 2008-3-17 11:47 发表


仔细看,在一个bucket中最多的行数竟然有2531行,因为bucket中是一个链表的结构,所以这几千行都是串在一个链表上。
由这一点想到这个Hash Table所依赖的hash key的distinct value可能太少,重复值太多。否则不应该会有这么多行在同一个bucket里面。



http://www.itpub.net/thread-955276-1-1.html


  隐约记得数据块被放到BUFFER的地址中是根据数据块的位置然后做一个什么MOD的动作

使用道具 举报

回复

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

本版积分规则 发表回复

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