驱动表选择

news/2024/11/29 0:33:53/

在提到SQL语句的执行计划时,我们常常提到驱动表,那么,什么是驱动表,驱动表一定是表吗?所谓驱动表,又称为外层表,就是在嵌套循环连接和哈希连接中,用来最先获得数据,并以此表的数据为依据,逐步获得其他表的数据,直至最终查询到所有满足条件的数据的第一个表。排序合并连接由于不存在优先访问那张表的顺序问题,因此也没有驱动表的概念。值得注意的是,驱动表并不一定指的是表,而是一个满足条件的记录的集合,Oracle依据这个集合,与其他的表的数据进行连接,这个集合叫做ROW SOURCE,即数据行源,顾名思义,就是由某个表中满足条件的数据行,组成子集合后,再以此子集合作为连接其他表的数据来源。这个子集合,才是真正的驱动表,有时候为了简洁,直接将最先按照条件或得子集合的那张表叫做驱动表。我们常说,驱动表一定是小表,指的是根据条件获得的子集合一定要小,而不是说实体表本身一定要小,大表如果获得的子集合小,一样可以简称这个大表为驱动表。 那么,究竟怎么写SQL,才能让Oracle按照我们的意愿,指定某个表作为驱动表呢?在采用RBO作为优化模式的情况下,SQL语句中表的书写顺序,以及WHERE条件的书写顺序非常重要,Oracle基本上按照这个顺序选择驱动表,但是在CBO模式下,Oracle会根据数据库中的统计信息,以及WHERE条件中的预估结果集,自己识别驱动表,如果统计信息不准确,或者我们的SQL写法不当,都会让CBO错误的选择驱动表。因此,在CBO模式下,表的顺序,WHERE条件的顺序,已不太重要,我们在写SQL时,非常重要的一点就是:根据业务逻辑,确定需要获得信息的主表,然后最大可能的在这个主表上增加限定条件,使得从该表上查询获得的数据最少,再根据这些数据上的字段,关联到其他表,在关联其他表时,最好选择与其他表的主键字段进行比较,或者与已经索引的字段进行比较,这样一来,就有意识地将业务需求的主表,作为驱动表处理了,Oracle也会在选择最优执行计划时,比较容易的找到驱动表。如果WHERE条件过于复杂,或者业务上获得信息的主表并不容易确定,我们可以根据业务的实际情况,评估关联各表的数据量和数据增长量,并分析关键条件字段的区分度,考虑在区分度高的字段,或者区分度高的组合字段上创建索引,以最大限度的降低某个表的结果集,增加其作为驱动表的机会。此外,如果由于WHERE条件不太明确等因素,导致Oracle在选择执行计划时,可能错误的选择驱动表,我们可以添加提示,固定leading表,则Oracle会按照我们的指定要求选择驱动表

 

1、 根据业务逻辑需求,有意识的给出驱动表的限定条件。

对于测试库的表Client_infoStaff_info两张表

 例:业务需求,通过已知客户的客户号,查找该客户的联系业务员的姓名。

 分析:这里已知条件为客户的客户号,很显然涉及到的主表是客户表,那么驱动表最好是client_info表,因为通过客户的客户号查询出来结果集以后,再根据这个结果集中的conta_agent,通过与staff_infoempno相等,直接利用staff_info的主键就可以快速获得数据,因此,就要千方百计限制通过客户的客户号查询出来的结果集。分析client_info表发现,这个字段为该表的主键,结果集本身就很小,因此SQL直接写成如下的方式即可:

Select b.emp_name from client_info a,staff_info b

Where a.clientno=:b1

And a.conta_agent=b.empno;

但是,万一很不幸,用户不是要求根据客户姓名来查找联系业务员,而是要求根据客户类型来查找来联系业务员姓名,这么一来,通过客户类型从client_info获得的数据量就很大,这个时候以client_info为驱动表就可能效率很不好,换作以staff_info表作为驱动的表的话,也需要全表扫描staff_info或者驱动数据,效率也不会很高。

这个时候,就需从业务的角度,分析能否尽可能的限定查询条件,例如查询某个客户类型下,特定证件号码的联系业务员(这种情况下,倾向staff_info表就作为驱动表);或某个客户类型下,特定服务业务员的某类客户的联系业务员(倾向以client_info为驱动表),一方面使得用户的查询更有实际意义,另一方面也能减少最终查询到的数据量,提高SQL效率。这是需要和用户沟通,也是需要我们在写SQL时尽量考虑的地方。

Select b.emp_name from client_info a,staff_info b

Where a.client_type=:b1

And b.emp_idno=:b2

And a.conta_agent=b.empno; ---staff_info为驱动表

 

Select b.emp_name from client_info a,staff_info b

Where a.client_type=:b1

And a.serve_agent=:b2

And a.conta_agent=b.empno; ---client_info为驱动表

2、 增加hint,强制某个表为驱动表

对于上面提到的情况,如果用户一定要求根据客户类型来查找联系业务员姓名,经分

析根据客户类型获得的数据结果集,可能比staff_info的业务员数据量要大得多,即使全表扫描staff_info表,效率也比先获得clinet_infoconta_agent,再查询联系业务员姓名要好的话,我们可以采用如下提示固定驱动表:

Select /*+ leading(b) full(b) use_hash(b,a)*/ emp_name from client_info a,staff_info b

Where a.client_type=:b1

And b.empno=a.conta_agent;

 

注意:分析思路如此,并不代表一定和实际的运行状况相同,SQL写好以后,最好看看执行计划,并带入实际的数据值进行测试验证。此外,示例仅为了说明问题,抛砖引玉,不一定与符合实际。

 


http://www.ppmy.cn/news/350433.html

相关文章

电机驱动板

电机驱动板 ——智能车实验室 BTS7960:智能功率芯片BTS7960是应用于电机驱动的大电流半桥高集成芯片。https://wenku.baidu.com/view/e50c2b62af1ffc4ffe47ac38.html74LS244:三态八缓冲器。 PWM: 脉冲宽度调制(PWM),是英文“Puse Width Modulation”的缩…

驱动表和被驱动表

判断方式 没有where条件时 左连接查询时前面的表是驱动表,后面的表是被驱动表右连接时相反内连接时哪张表数据少哪张表是驱动表 有where条件时 带where条件的是驱动表,否则是被驱动表 连接查询的算法 简单嵌套循环连接算法 一旦确定了驱动表和被驱动表…

使用uni-live-pusher 和 uni-live-player 组件开发小程序直播功能

Uniapp开发文档中没有直接提供小程序直播功能的API,需要自己通过调用第三方SDK或者封装相关API实现。下面介绍一些可能实用的组件和工具: uni-live-pusher 和 uni-live-player 组件:这两个组件可以实现小程序直播推流和播放器功能&#xff0c…

测试驱动

加密错误代码记录: eyBbIjEyMzAiXT17IFsi0qrJvrP9tcTOxLzwdCx7SJdPXsgWzFdPSJGRGF0YVxccmVnaXN0X3NjZW5lLmRhdCIsWzJdPSJXZWJHYW1lLmJpbiIsWzNdPSJXZWJHYW1lLmRhdCIgfSxbIrj80MLLtcP3Il09ItDeuLSyu9fUtq/X6bbTzsrM4iFcCtPFu6/X1LavyfHG9yzQ3ri0vLrWqs7KzOIsxcWz/dbY0qrO78a3sru…

驱动表

驱动表(driving table/outer table)又称为外层表,驱动表仅仅用于nested loops join 和 hash join 驱动表是用来驱动查询的 在cbo中,优化器会根据cost自动选择驱动表,与表的顺序无关。 通常情况下,驱动表的选择性较高(该列唯一键…

Realsense d435i驱动安装、配置及校准

写在前面 本文是在ubuntu20.04下安装,其它版本大同小异。可能出现的问题,主要由各自安装相关库版本不一致导致,故问题不一,但一般很好解决,正常情况下不会出现。 Intel Realsense 深度摄像头D435i将D435强大的深度感知…

英特尔® 驱动程序和支持助理 (intel-driver-support-assistant) 安装后无法扫描电脑硬件驱动解决

intel(intel-driver-support-assistan)驱动助手下载地址 https://www.intel.cn/content/www/cn/zh/support/detect.html 1.如题我安装intel驱动助手后打开跳转到页面去没有出现扫描 2. 开始解决: 1) 确认intel驱动助手已安装&am…

Benq!!!

今天做题的时候发现了一个神仙 美国普林斯顿大学的Benq,这个人三年前注册了Codeforces的账号,刚注册的时候评分一度掉到1200,在他最低谷的那场比赛,B题是难度1200的贪心,他交了八遍没有过,最后以失败告终。…