通过图表简化sql语句的表关联

在之前的博文中分享过一个执行了两天的一条sql语句,走了两个大表的扫描,导致执行时间很长,通过简化sql做了不小的改进,今天我们来看看还可以做些什么。
上次简化后的语句如下:
with tmp_logical_date as (SELECT logical_date
                  FROM logical_date
                 WHERE logical_date_type = 'R'
                   AND expiration_date IS NULL)
SELECT trim(TO_CHAR(COUNT(distinct coll.entity_id), '000000000'))
  FROM cl1_coll_entity coll,
       table_bpm_step_inst bpm,
       table_bpm_step,
       ar1_account,
       csm_account,
       csm_pay_channel,
       customer,
       subscriber,
       ar1_billing_arrangement,
       ar1_address_name,
       charge_distribute,
       tmp_logical_date
 WHERE coll.entity_id(+) = csm_account.ban
   AND coll.proc_inst_id = bpm.parent2proc_inst
   AND bpm.step2step = table_bpm_step.objid
   AND bpm.status = 30
   AND coll.entity_id = ar1_account.account_id
   AND csm_account.ban = csm_pay_channel.ban
--   AND ar1_account.account_id = ar1_aged_trial_balance.account_id
   AND csm_account.customer_id = customer.customer_id
   AND csm_account.customer_id = subscriber.customer_id
   AND ar1_account.account_id = ar1_billing_arrangement.account_id
   AND ar1_account.account_id = ar1_address_name.account_id
   AND ar1_address_name.address_type = 'ACC'

  and exists(
  (SELECT 1
          FROM ar1_aged_trial_balance
         WHERE aged_type = 'D'
           AND group_type = 'B'
           AND status = 'EFF'
           AND TRUNC(tmp_logical_date.logical_date - due_date) >= 0
           AND account_id = coll.entity_id
         )

  )
   AND subscriber.trx_id = charge_distribute.trx_id
   AND subscriber.subscriber_no = charge_distribute.agreement_no
   AND charge_distribute.target_pcn = csm_pay_channel.pym_channel_no
   AND csm_account.ban = csm_pay_channel.ban
   AND EXISTS
 (SELECT null--cl1_treatment_activity.entity_id
          FROM cl1_treatment_activity, table_bpm_step_inst, table_bpm_step
         WHERE cl1_treatment_activity.step_id = table_bpm_step_inst.objid
           AND table_bpm_step_inst.step2step = table_bpm_step.objid
           AND table_bpm_step.NAME LIKE '%IVR%'
           AND table_bpm_step_inst.status = 65
           AND TO_DATE(TO_CHAR(cl1_treatment_activity.activity_date,
                               'YYYYMMDD'),
                       'YYYYMMDD') =tmp_logical_date.logical_date
           AND cl1_treatment_activity.entity_id = csm_account.ban)

单纯来看这么多表的关联,着实是一个很棘手的事情,十多张大表关联,从技术角度来看,oracle的分析确实还是很细致的,根据数据量,走索引的地方都走了索引,预估的数据量也差不离。
但是想对这条语句做进一步的改进,单纯调整执行计划还是很有限制的。
我们来看看一个新的方法,首先我已经被这些表关联弄晕了,我简单整理了下面的图表。这个图表能够很清楚的看到表连接的情况。

表的数据都是基于cl1_coll_entity,但是通过这个图发现,重心似乎转移了。感觉重心似乎是csm_account
我们来看看csm_account和cl1_coll_entity的关联,使用了一个外连接,即对于csm_account中的关联数据在cl1_coll_entity都存在。csm_account的数据是最全的。
coll.entity_id(+) = csm_account.ban
明白了这一点,我们来看看红色框内的表连接,既然csm_account中的数据是完整的,类似一个全表扫描,那么后面的一个环形表连接就是多余的。因为方框中的表连接都是业务层面,是这些entity之间的完全映射。这些表中没有额外的过滤条件。
可以通过一个简单的例子来说明。我们创建两个表csm_account,cl1_coll_entity
create table csm_account(id number);
insert into csm_account values(1);
insert into csm_account values(2);
insert into csm_account values(3);

create table cl1_coll_entity(id number);
insert into cl1_coll_entity values(1);

select coll.id from cl1_coll_entity coll,csm_account
where coll.id(+)=csm_account.id
        ID
----------
         1

3 rows selected.
select count(coll.id) from cl1_coll_entity coll,csm_account
where coll.id(+)=csm_account.id
COUNT(COLL.ID)
--------------
             1
1 row selected.
因为cl1_coll_entity中的数据是csm_account中的子集,所以后面csm_account的完全映射丝毫不会对cl1_coll_entity的数据有任何的影响。既然没有任何的影响,就不需要保留它了。
同理标红的ar1_billing_arrangement和ar1_account中的数据是多对一的映射。这个也是完全从业务层面保证。
简化后的表连接情况如下:


可以看到原本14个表连接最后简化为了8个表连接,简化的幅度还是比较大的。
这种简化思路可以在平时的调优中参考,从业务层面能够完全保证的数据情况反复关联就显得有些冗余了。毕竟从技术层面我们无法得到更多的细节。
不管怎么样,都是为了简化逻辑,减少资源的消耗。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263701.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

输入三个数,按照由大到小的顺序输出

voidswap(int*p1,int*p2)/*实现两个数交换的函数*/{inttemp; temp*p1;*p1*p2;*p2temp;}voidexchange(int*p1,int*p2,int*p3)/*实现3个数两两比较、交换的函数*/{if(*p1<*p2) swap(p1,p2);/*比较第一个数和第二个数*/if(*p1<*p3) swap(p1,p3);/*比较第一个数和第三个数*/i…

android 自定义text,android – 使用自定义textSize实现自定义TextView

我已经实现了自定义TextView,然后我需要更改其文本大小以供将来使用.在那一步,我决定使用style.xml和attr.xml进行textSize自定义但是,当我的自定义布局膨胀时,我收到运行时错误.与我为了自定义而更改的部件相关的错误.这是我实现的代码片段.attr.xmlstyles.xml?attr/right_de…

[翻译] BFKit

BFKit BFKit is a collection of useful classes to develop Apps faster. BFKit是一个有用的工具集合&#xff0c;帮助你快速开发。 Installing and Usage Pod Pod安装 Create a Podfile in your project directoryWrite:platform :ios, 7.0xcodeproj Project.xcodeproj pod …

Camera Vision - video surveillance on C#

http://www.codeproject.com/KB/audio-video/cameraviewer.aspx 开发的资源 介绍&#xff1a;纵观当今的监控系统的发展趋势&#xff0c;能很容易发现基于IP的解决方案正在迅速的普及。有许多的制造商&#xff0c;提供广泛的IP视频射像和视频服务器&#xff0c;意味着个人的IP…

android 接口定义常量,Android开发笔记(5):常量的合理使用

今天&#xff0c;我们来聊一些“细枝末节”的问题——java中的常量。觉得很有意思&#xff0c;给大家分享一下&#xff1a;下面是我见过的几种常量定义操作&#xff1a;1.普通款&#xff1a;public class Constants {private Constants(){}public static final int MAX Intege…

mysql数据库操作手册

1 存储过程的写法 以下是一个带有入参的存储过程模板&#xff0c; #删除方案-存储过程 CREATE PROCEDURE procPersonAppointRecallPlanByPlanUuidDelete(in planUuid varchar(48)) BEGIN update PERSON_APPOINT_RECALL_DUTY set duty_status 2 WHERE duty_list_uuid in (sel…

如何写 go 代码 (How to Write Go Code 翻译)

目录 1. 写在前面的话2. 介绍3. 代码组织 3.1. 工作区3.2. GOPATH 环境变量3.3. Package 路径3.4. 第一个 GO 程序3.5. 第一个 GO 库3.6. Package name4. 测试5. 远程 package6. 下一步7. 获取帮助写在前面的话 本文为Go官方网站 How to Write Go Code 这篇文章的翻译, 水平有限…

Servlet规范定义的Servlet 生命周期

Servlet有良好的生存期的定义&#xff0c;包括如何加载、实例化、初始化、处理客户端请求以及如何被移除。这个生存期由javax.servlet.servlet接口的init,service和destroy方法表达。1、加载和实例化 容器负责加载和实例化一个Servlet。实例化和加载可以发生在引擎启动的时候&…

android auto 源代码,最近心血来潮,把Androidautosize的源码搂了一眼

https://codechina.csdn.net/mirrors/jessyancoding/androidautosize?utm_sourcecsdn_github_accelerator以上是Androidautosize的源码&#xff0c;有兴趣的就去下下来搂一眼我这边还没看完&#xff0c;就把最基础的看了一下&#xff0c;然后顺了下简单的流程&#xff0c;顺便…

11次作业

1、实验要求&#xff1a;建立一个通信录&#xff0c;通信录的结构体记录包括&#xff1a;姓名、生日、电话号码&#xff1b;其中生日又包括三项&#xff1a;年、月、日。编写程序&#xff0c;定义一个嵌套的结构类型&#xff0c;输入n&#xff08;n<10&#xff09;个联系人的…

Lucene.net 下载地址

Lucene.net 官方网站 http://lucene.apache.org/lucene.net/ Lucene.net 2.9.2 下载地址 Lucene.Net_2_9_2/ 转载于:https://www.cnblogs.com/leco/archive/2010/12/22/1913806.html

android内存卡测试,安卓sd卡真假检测工具_内存卡检测扩容卡软件_sd insight

内存卡检测扩容卡软件内存卡检测扩容卡软件由于U盘、TF卡&#xff0c;sd内存卡等移动存储设备越来越便宜&#xff0c;导致很在某宝上买到便宜且容量大的U盘或者内存卡&#xff0c;结果基本上都是扩容盘&#xff0c;所谓扩容盘&#xff0c;就是实际容量比如2G的U盘&#xff0c;经…

bashrcprofile

# /etc/bashrc# are we an interactive shell? 是交互式的shell吗&#xff1f;# System wide functions and aliases //系统功能和别名比如说&#xff1a;你设置个别名alias xixdate当你键入xix时&#xff0c;那么系统显示为命令date的信息。&#xff08;键入后才输出&#…

android ftp权限,实战android手机telnet、ftp登陆,权限修改

问题的提出&#xff1a;我用的手机是HTC magic&#xff0c;sd卡用的是金士顿的&#xff0c;不知道什么原因&#xff0c;总是有时能找到sd卡&#xff0c;有时找不到。我个人总有一些数据文件&#xff0c;想固定放在手机的系统上&#xff0c;而不是sd卡上(/sdcard)&#xff0c;那…

Linux nohup和的功效

Linux nohup和&的功效 https://www.cnblogs.com/laoyeye/p/9346330.html 这是我转载的文章&#xff0c;写的很好&#xff0c; nohup Command [ Arg ... ] [ & ] &&#xff1a;进程后台执行 不挂断地运行命令。no hangup的缩写&#xff0c;意即“不挂断” 例如&…

获取手机通讯录跟sim卡通讯录

/** 获取库Phone表字段 **/ private static final String[] PHONES_PROJECTION new String[] { Phone.DISPLAY_NAME, Phone.NUMBER }; private List<ContactsModel> contactsModels new ArrayList<ContactsModel>(); /** 得到手机通讯录联系人信息 **/ …

如何去掉ECShop 2.7.2中的Powered by ECShop字符

1.去掉标题上Powered by ECShop的字样如下: 在includes/lib_main.php找到lib_main.php文件,打开后,找到136行,将$page_title $GLOBALS[’_CFG’][’shop_title’] . ‘ – ‘ . ‘Powered by ECShop’ ;改为$page_title $GLOBALS[’_CFG’][’shop_title’] ;当然, . ‘ – ‘…

proguard android 配置,android – Proguard忽略库的配置文件

我现在面对一个非常奇怪的问题吗&#xff1f;我有一个具有两个模块的Gradle应用程序&#xff0c;一个主要模块和一个库模块。>在两个模块中&#xff0c;我已经声明了一个正确的proguard-rules.pro文件路径>在两个.gradle文件中我有minifyEnabled为true这是第一个问题&…

MySql Workbench 安全模式(safe mode)

默认情况下&#xff0c;MySql WorkBench 的安全模式是打开的&#xff0c;即&#xff1a;update、delete语句必须带 where 条件字句&#xff0c;单条记录更新或删除。 如果关闭安全模式&#xff08;safe mode&#xff09;&#xff1a; 菜单栏&#xff1a;编辑(Edit) ---> 个…