首页 > 其他分享 >谓词推入-push_pred

谓词推入-push_pred

时间:2023-09-26 21:01:48浏览次数:42  
标签:pred 视图 谓词 SQL push where 连接 推入

概念描述

谓词推入(Pushing Predicate):当 SQL 语句中包含不能合并的视图,同时视图有谓词过滤(也就是 where 过滤条件), CBO 会将谓词过滤条件推入视图中,这个过程就叫作谓词推入。
谓词推入的主要目的就是让 Oracle 尽可能早地过滤掉无用的数据,从而提升查询性能。
为什么谓词推入必须要有不能被合并的视图呢?因为一旦视图被合并了,执行计划中根本找不到视图,这个时候谓词往哪里推呢?所以谓词推入的必要前提是 SQL 中要有不能合并的视图。

测试验证

我们先创建一个不能被合并的视图(视图中有 union all)。

create or replace view v_pushpredicate as
  select * from test
  union all
  select * from test where rownum>=1;

查看执行计划

select * from v_pushpredicate where object_id<10;

谓词推入-push_pred_SQL


SQL 语句中, where 过滤条件是针对视图过滤的,但是从执行计划中(Id=4)我们可以看到, where 过滤条件跑到视图中的表中进行过滤了,这就是谓词推入。因为视图中第二个表有rownum, rownum 会阻止谓词推入,所以第二个表走的是全表扫描,需要到视图上进行过滤(Id=1)。

如果 VIEW 前面有“*”号,这就说明有谓词没有推入到视图中。

还有一种谓词推入,是把连接列当作谓词推入到视图中,这种谓词推入我们一般叫作连接列谓词推入,此类谓词推入最容易产生性能问题。

create or replace view v_pushpredicate as
  select * from test
  union all
  select * from test;

添加 HINT:push_pred 提示将连接列推入到视图中

select /*+ push_pred(b) */ *
  from test a, v_pushpredicate b
  where a.object_id = b.object_id
  and a.owner = 'SCOTT';

谓词推入-push_pred_谓词推入_02

将连接列推入到视图中这种谓词推入,一般在执行计划中都能看到 PUSHED PREDICATE或者 VIEW PUSHED PREDICATE,而且视图一般作为嵌套循环的被驱动表,同时视图中谓词被推入列有索引。这种谓词推入对性能有好有坏。为什么连接列谓词推入,被推入的视图一般都作为嵌套循环的被驱动表呢?这是因为连接列谓词推入需要传值(传值到视图里面),而有传值操作的表连接方法只有嵌套循环或者 FILTER。 FILTER 是专门针对半连接或者反连接的(where 后面的子查询),谓词推入是专门针对 from 后面的子查询,所以连接列谓词推入,被推入的视图一般都作为嵌套循环的被驱动表。

去掉 HINT:push_pred

select *
  from test a, v_pushpredicate b
  where a.object_id = b.object_id
  and a.owner = 'SCOTT';

谓词推入-push_pred_执行计划_03


如果不将连接列推入到视图中,视图里面的表就只能全表扫描,这时性能远不如索引扫描。

知识总结

如果遇到执行计划中 VIEW PUSHED PREDICATE 一定要注意,如果 SQL 执行很快,不用理会;如果 SQL 执行很慢,可以先关闭连接列谓词推入(alter session set “_push_join_predicate” = false)功能,再逐步分析为什么连接列谓词推入之后, SQL 性能很差。连接列谓词推入性能变差一般是CBO 将驱动表 Rows 计算错误(算少),导致视图作为嵌套循环被驱动表,然后一直反复被扫描;也有可能是视图太过复杂,视图本身存在性能问题,这时需要单独优化视图。例如视图单独执行耗时 1 秒,在进行谓词推入之后,视图会被扫描多次,假设扫描 1 000 次,每次执行时间从 1 秒提升到了 0.5 秒,但是视图被执行了 1 000 次,总的耗时反而多了,这时谓词推入反而降低性能。
一定要注意,当视图中有 rownum 会导致无法谓词推入,所以一般情况下,我们不建议在视图中使用 rownum。为什么 rownum 会导致无法谓词推入呢?这是因为当谓词推入之后,rownum 的值已经发生改变,已经改变了 SQL 结果集,任何查询变换必须是在不改变 SQL 结果集的前提下才能进行。

标签:pred,视图,谓词,SQL,push,where,连接,推入
From: https://blog.51cto.com/u_13482808/7614504

相关文章

  • sql优化-谓词推入push_pred
    问题概述如下所示的一条SQL(对相关对象信息做了脱敏处理),出现性能退化。select*from(selectstatus,odate,ccode,manabcode,bcode,wcode,jcode,ordicodex,......
  • 高效的浏览 Linux 目录结构:pushd和popd命令
    在这个教程中,我们将讨论两个相关的命令:pushd和popd,使用它们可以高效的浏览Linux目录结构。这两个命令在大多数 shell ,比如bash、tcsh中都存在。pushd和popd命令在Linux系统中如何工作pushd和popd命令根据‘LIFO’(后进先出)原则工作。在这个原则之下,只有两个操作是允......
  • Hbase MapReduce例子
    HbaseMapreduce例子http://hadoop.apache.org/hbase/docs/current/api/org/apache/hadoop/hbase/mapreduce/package-summary.html#package_descriptionhttp://wiki.apache.org/hadoop/Hbase/MapReduce (Deprecated) 需要重启Hadoop的方式所有机器都有修改配置1:修改$HADOOP_HOME/......
  • hadoop中mapred.tasktracker.map.tasks.maximum的设置
    目前,我们邮件的一部分log已经迁移到Hadoop集群上并由Hive来执行相关的查询hadoop中默认的mapred.tasktracker.map.tasks.maximum设置是2也即:每一个tasktracker同时运行的map任务数为2照此默认设置,查询80天某用户的操作日志,耗时5mins,45sec经过测试,发现将mapred.tasktracker.map.ta......
  • 实现mapreduce多文件自定义输出
     普通maprduce中通常是有map和reduce两个阶段,在不做设置的情况下,计算结果会以part-000*输出成多个文件,并且输出的文件数量和reduce数量一样,文件内容格式也不能随心所欲。这样不利于后续结果处理。如果只是想做到输出结果的文件名可控,实现自己的LogNameMultipleTextOutputFormat类,......
  • git add,conmmit,pull,push的顺序问题
    本地仓库和本地分支有什么区别?答:本地有工作区和版本库,版本库有暂存区,和分支,本地分支属于本地仓库里,是包含关系,一个仓库里可以有很多分支。commit是提交到本地仓库,然后push,这个push是把所有代码推到远程仓库,还是只是把commit的地方推到远程仓库?答:肯定不会全量推送到远程的,是通......
  • 穿越人海遇见你:Mobpush是如何实现智能化精准投放的
    精准投放的概念由来已久,在这个“内容为王”的信息爆炸时代,已经不仅仅是用户在单向的凭着自己的喜好筛选推送,同时也是推送运营者在主动的根据推文内容筛选其潜在的受众,对客户在收入、消费习惯、年纪、兴趣爱好的了解越多,就越可能激发用户点击推送的兴趣,从而提升成交转化率,实现推送投......
  • JS push()方法
    定义和用法push()方法可向数组的末尾添加一个或多个元素,并返回新的长度。语法arrayObject.push(newelement1,newelement2,....,newelementX)参数描述newelement1必需。要添加到数组的第一个元素。newelement2可选。要添加到数组的第二个元素。newelementX可选。可添加多个元......
  • git push/pull 本地分支名:远程分支名
    全局fetch:代表用于拉取的远程仓库push:代表用于提交的远程仓库origin:远程仓库的别名(alias)。执行gitremote-v可以看到一、拉取远程分支master到本地temp分支(没有temp会自动创建)在本地新建一个temp分支,并将远程仓库的master分支的代码下载到本地分支上面,这样的好......
  • window.history.pushState()和window.history.replaceState()
    今天在项目中遇到要实现修改地址栏但是页面不可以刷新的需求查阅资料发现可以用window.history.pushState(state,title,url)和window.history.replaceState(state,title,url)三个参数:state:一个与添加的记录相关联的状态对象,主要用于popstate事件。该事件触发时,该对象会传......