前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Oracle SQL 性能调优:使用Hint固定执行计划1(Hash Join)

Oracle SQL 性能调优:使用Hint固定执行计划1(Hash Join)

作者头像
SQLplusDB
发布于 2022-08-19 12:17:05
发布于 2022-08-19 12:17:05
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

编者按:

本文作者系杨昱明,现就职于甲骨文公司,从事数据库方面的技术支持。希望能通过发表文章,把一些零散的知识再整理整理。个人主页:https://blog.csdn.net/weixin_50513167,经其本人授权发布。

Hash Join 是不使用索引等价结合时,最有效的结合方式,所以,使用的机会非常之多。

Hash Join 是在内存中作出 Hash Table 用来存放结合数据。通常,会先访问数据量少的表,之后再访问数据量多的表,这样能保证性能。

先访问的表叫做 Build表,第二个访问的表叫做 Probe表。那么假如 3个以上的表进行 Hash Join 时,各表之间的结合顺序,以及那个表作为 Build表,那个表作为 Probe表,如何来控制呢。

下面我们介绍一下相关的 Hint 来进行有效的控制。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LEADING Hint (指定 Hash Join 顺序)
SWAP_JOIN_INPUTS Hint(指定 Build 表)
NO_SWAP_JOIN_INPUTS Hint(指定 Probe 表)
USE_HASH (指定使用 Hash Join)

下面用几个例子来做一下展示。

准备:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
drop table t1 purge;
drop table t2 purge;
drop table t3 purge;
create table t1(c1 number, c2 number);
create table t2(c1 number, c2 number);
create table t3(c1 number, c2 number);
insert into t1 values (1,1);
insert into t2 values (1,2);
insert into t3 values (1,3);
commit;

Case 1:

结合顺序是 A->B(Build 表)->C

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SQL> select /*+ leading(a b c) use_hash(b c) swap_join_inputs(b) */ * from t1 a, t2 b, t3 c where a.c1=b.c1 and a.c1=c.c1;


        C1         C2         C1         C2         C1         C2
---------- ---------- ---------- ---------- ---------- ----------
         1          1          1          2          1          3


Execution Plan
----------------------------------------------------------
Plan hash value: 1184213596


----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |     1 |    78 |     9   (0)| 00:00:01 |
|*  1 |  HASH JOIN          |      |     1 |    78 |     9   (0)| 00:00:01 |
|*  2 |   HASH JOIN         |      |     1 |    52 |     6   (0)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| T2   |     1 |    26 |     3   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| T1   |     1 |    26 |     3   (0)| 00:00:01 |
|   5 |   TABLE ACCESS FULL | T3   |     1 |    26 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   1 - access("A"."C1"="C"."C1")
   2 - access("A"."C1"="B"."C1")

Case 2:

结合顺序是 A->B(Build表)->C(Build表)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SQL> select /*+ leading(a b c) swap_join_inputs(b) swap_join_inputs(c) */ * from t1 a, t2 b, t3 c where a.c1=b.c1 and a.c1=c.c1;


        C1         C2         C1         C2         C1         C2
---------- ---------- ---------- ---------- ---------- ----------
         1          1          1          2          1          3


Execution Plan
----------------------------------------------------------
Plan hash value: 1487401159


----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |     1 |    78 |     9   (0)| 00:00:01 |
|*  1 |  HASH JOIN          |      |     1 |    78 |     9   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL | T3   |     1 |    26 |     3   (0)| 00:00:01 |
|*  3 |   HASH JOIN         |      |     1 |    52 |     6   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| T2   |     1 |    26 |     3   (0)| 00:00:01 |
|   5 |    TABLE ACCESS FULL| T1   |     1 |    26 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   1 - access("A"."C1"="C"."C1")
   3 - access("A"."C1"="B"."C1")

Case 3:

结合顺序是 A->C(Build表)->B

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SQL> select /*+ leading(a c b) USE_HASH(c b) swap_join_inputs(c) */ * from t1 a, t2 b, t3 c where a.c1=b.c1 and a.c1=c.c1;


        C1         C2         C1         C2         C1         C2
---------- ---------- ---------- ---------- ---------- ----------
         1          1          1          2          1          3




Execution Plan
----------------------------------------------------------
Plan hash value: 2467348796


----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |     1 |    78 |     9   (0)| 00:00:01 |
|*  1 |  HASH JOIN          |      |     1 |    78 |     9   (0)| 00:00:01 |
|*  2 |   HASH JOIN         |      |     1 |    52 |     6   (0)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| T3   |     1 |    26 |     3   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| T1   |     1 |    26 |     3   (0)| 00:00:01 |
|   5 |   TABLE ACCESS FULL | T2   |     1 |    26 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   1 - access("A"."C1"="B"."C1")
   2 - access("A"."C1"="C"."C1")

另外,以上面的例子来说,可以用 C->B->A 的顺序进行 Hash Join 吗。不可以哈,因为 B表和 C表之间没有结合键,这样会产生笛卡尔积。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SQL> select /*+ leading(c b a) USE_HASH(c b) */ * from t1 a, t2 b, t3 c where a.c1=b.c1 and a.c1=c.c1;


        C1         C2         C1         C2         C1         C2
---------- ---------- ---------- ---------- ---------- ----------
         1          1          1          2          1          3




Execution Plan
----------------------------------------------------------
Plan hash value: 2210115829


------------------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |     1 |    78 |     9   (0)| 00:00:01 |
|*  1 |  HASH JOIN            |      |     1 |    78 |     9   (0)| 00:00:01 |
|   2 |   MERGE JOIN CARTESIAN|      |     1 |    52 |     6   (0)| 00:00:01 |
|   3 |    TABLE ACCESS FULL  | T3   |     1 |    26 |     3   (0)| 00:00:01 |
|   4 |    BUFFER SORT        |      |     1 |    26 |     3   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL | T2   |     1 |    26 |     3   (0)| 00:00:01 |
|   6 |   TABLE ACCESS FULL   | T1   |     1 |    26 |     3   (0)| 00:00:01 |
------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   1 - access("A"."C1"="B"."C1" AND "A"."C1"="C"."C1")
————————————————
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SQL和数据库技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Python实现计算机屏幕任意区域截图
程序功能与用法:运行后有个主窗体,上面有个按钮,单击后开始截图,鼠标坐标落下开始截图,鼠标左键抬起表示截图结束,然后弹出对话框提示保存截图文件。 本文要点在于Python扩展库pillow提供的ImageGrab支持全屏幕或指定区域的截图。 import tkinter import tkinter.filedialog import os from PIL import ImageGrab from time import sleep #创建tkinter主窗口 root = tkinter.Tk() #
Python小屋屋主
2018/04/16
6.2K0
用python实现选择截图区域
一直想用python实现一个类似QQ截图的功能,但不直接截图,而是返回截图的区域,以下是代码
py3study
2020/01/10
3.8K0
Python实现屏幕取色器功能
代码主要思路:首先获取全屏幕截图,在截取的图像上获取指定位置的像素颜色值并转换为十六进制表示形式。 遗憾之处:这个程序的部分代码比较长,在手机上查看时这些换行可能会影响阅读质量,记得之前有个朋友提过建议让我加上代码块,不过我试了试,微信公众号后台的编辑器不支持这个功能,网上找了几个编辑器也不太好用。如果有朋友知道简单易用的支持代码块的编辑器还请推荐一下,谢谢! import os from time import sleep import tkinter import tkinter.filedialog
Python小屋屋主
2018/04/17
7.9K3
Python: 屏幕取色器(识别屏幕上不同位置的颜色)
文章背景:工作中,有时候需要判断图片中不同位置的颜色。有些颜色不太容易区分,所以想通过Python编写代码,通过屏幕取点,获取某个位置的颜色值。
Exploring
2022/09/20
5.2K0
Python:  屏幕取色器(识别屏幕上不同位置的颜色)
基于tkinter的GUI编程
tkinter:tkinter是绑定了Python的TKGUI工具集,就是Python包装的Tcl代码,通过内嵌在Python解释器内部的Tcl 解释器实现的,它是Python标准库的一部分,所以使用它进行GUI编程不需要另外安装第三方库的。
py3study
2020/01/16
5.6K0
基于tkinter的GUI编程
Python实现局域网内屏幕广播的技术要点分析
为更好地保证教学质量和提高学生的学习积极性,我使用Python开发了一套课堂教学管理系统,具有在线点名、在线答疑、随机提问、在线作业管理、在线自测、在线考试、数据汇总、试卷生成、屏幕广播等功能,教师端
Python小屋屋主
2018/04/16
1.5K0
Python实现局域网内屏幕广播的技术要点分析
Python使用tkinter打造自定义对话框完整代码
问题来源:前一阵发过一个技术文章Python编写抽奖式随机提问程序,其中有个弹出式对话框,好像上海科技大学宋老师在群里当时问了一句对话框中中奖姓名是否能显示的大一些,如图: 当时记得标准的tkinte
Python小屋屋主
2018/04/16
3.1K0
Python使用tkinter打造自定义对话框完整代码
tkinter: 事件 & 绑定 (Events and Bindings)
目的 tkinter 获取 键盘输入 与 鼠标输入 。 实现代码 # coding=utf-8 import tkinter as tk root = tk.Tk() def center_window(w, h): # 获取屏幕 宽、高 ws = root.winfo_screenwidth() hs = root.winfo_screenheight() # 计算 x, y 位置 x = (ws/2) - (w/2) y = (hs/2) - (
JNingWei
2018/09/28
7650
Python 图形化界面基础篇:处理鼠标事件
在 Python 图形用户界面( GUI )应用程序开发中,处理鼠标事件是一项重要的任务。鼠标事件包括点击、双击、移动、释放等操作,通过捕获这些事件,你可以实现各种交互功能,如绘图、拖放、点击按钮等。在本文中,我们将深入研究如何使用 Python 的 Tkinter 库来处理鼠标事件,并演示如何在应用程序中实现一些常见的鼠标交互功能。
小蓝枣
2023/09/17
1.2K0
Python 图形化界面基础篇:处理鼠标事件
python截图识别文字_python截图并转换文字「建议收藏」
本文主要介绍了使用pyHook、pythoncom、pytesseract、PIL、win32api等module实现python的截图识别文字功能。
全栈程序员站长
2022/08/13
3.4K0
python截图识别文字_python截图并转换文字「建议收藏」
python tkinter 简单实例
# 1920*1080    表示在屏幕在宽度上上有1920个点, 高度上有1080个点
用户7886150
2020/12/28
2.6K0
python tkinter 设计指南
pack() 是一种较为简单的布局方法,在不使用任何参数的情况下,它会将控件以添加时的先后顺序,自上而下,一行一行的进行排列,并且默认居中显示。pack() 方法的常用参数如下所示:
独元殇
2023/03/21
7.1K0
tkinter -- Event(1)
分别测试鼠标的 Relase 事件,只有当鼠标被 Relase 后移动才回产生 Relase 事件
py3study
2018/08/03
5190
python3 五子棋(tkinter)
BOARD_WIDTH = 535 BOARD_HEIGHT = 536 BOARD_SIZE = 15
用户5760343
2019/12/12
1K0
Python写一个像QQ可快捷键唤起区域截屏的应用
1).首先要能响应快捷键调起截屏程序,像QQ使用Ctrl+shift+B可以截屏一样;
一墨编程学习
2019/05/30
2.4K1
Python--TKinter
GUI介绍 GraphicalUserInterface GUI for Python: TKinter, wxPython, PyQt TKinter: 绑定的是TK GUI工具集,用Python包装的Tcl代码 PyGIK TKinter的替代品 wxPython 跨平台的Python GUI PyQt 跨平台的 商业授权可能有问题 推荐资料 辛星GUI,辛星Python(简洁、清晰) Python GUI Programming cookbook TKinter reference a GUI for
ruochen
2021/05/11
5.3K0
Python--TKinter
快乐游戏,解放双手
上回说到这个PyUserInput这个库能够模拟鼠标和键盘点击(没看过的朋友底部有传送门),今天老肥再来实战一波游戏脚本制作。
老肥码码码
2020/02/26
3500
快乐游戏,解放双手
tkinter学习系列(二)之窗口的设置
目录 (一)窗体的最小框架 1.说明: 2.源代码: 3.实现效果: (二)窗体的基本设置 1.说明: 2.完整代码: 3.实现效果: (三)窗体的外形设置 1.说明: 2.完整代码: 3.实现效果: (四)窗体的三个方法: 1.获取屏幕的大小 2.获取窗体的大小 3.获取窗体的位置 目录: 1.窗体的最小框架 2.窗体的基本设置 3.窗体的外形设置 (一)窗体的最小框架 1.说明: 需要导入标准库: import tkinter 2.源代码: # 导入模块,并取别名 impor
py3study
2020/01/17
1.1K0
python-tkinter(7) 实现各种个样的撩妹鼠标拖尾
系统的拖尾已经无法满足我们了,女朋友叫你把鼠标拖尾换成她的照片,让你时时刻刻都可以看见她,这个要求你答不答应。
全栈程序员站长
2022/07/19
7340
python-tkinter(7) 实现各种个样的撩妹鼠标拖尾
python-tkinter 实现各种个样的撩妹鼠标拖尾
系统的拖尾已经无法满足我们了,女朋友叫你把鼠标拖尾换成她的照片,让你时时刻刻都可以看见她,这个要求你答不答应。
大家一起学编程
2021/09/18
7300
python-tkinter 实现各种个样的撩妹鼠标拖尾
相关推荐
Python实现计算机屏幕任意区域截图
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档