찾다
데이터 베이스MySQL 튜토리얼Oracle11g新特性之动态变量窥视
Oracle11g新特性之动态变量窥视Jun 07, 2016 pm 03:12 PM
동적변하기 쉬운새로운 특성특성

欢迎进入Oracle社区论坛,与200万技术人员互动交流 >>进入 1. 11g之前的绑定变量窥视 我们都知道,为了能够让SQL语句共享执行计划,oracle始终都是强调在进行应用系统的设计时,必须使用绑定变量,也就是用一个变量来代替原来出现在SQL语句里的字面值。比如

欢迎进入Oracle社区论坛,与200万技术人员互动交流 >>进入

        1. 11g之前的绑定变量窥视

        我们都知道,为了能够让SQL语句共享执行计划,oracle始终都是强调在进行应用系统的设计时,必须使用绑定变量,也就是用一个变量来代替原来出现在SQL语句里的字面值。比如,对于下面三条SQL语句来说:

         select col1 from t where col2 = 1;
        select col1 from t where col2 = 2;
        select col1 from t where col2 = 3;

        我们可以看到,这三条SQL语句几乎一样,只有最后where条件里的字面值(分别是1、2、3)不同而已。但是如果写成这个样子,则oracle是不知道这三条SQL语句是一样的,仍然把它们当作三条完全不同的SQL语句,从而在shared pool里进行硬解析,并生成最终的执行计划。但是我们会发现,这三个执行计划可能都是一样的,因此后面两次生成执行计划的工作可能是完全不必要的,这在典型的OLTP环境中更是如此。由于解析本身属于CPU密集型操作,因此为了降低对CPU的消耗,oracle建议将这样的SQL写成:

         select col1 from t where col2 = :v1;

        然后,分别将1、2、3传递给v1,这样的话,只需要第一次传入1时进行解析即可。而后面执行2、3时,由于SQL文本本身没有变化,因此直接把执行计划拿来使用即可,不需要再次生成执行计划。

        但是,生成执行计划本身是基于概率的理论,在不访问具体表里的数据的前提下,根据你的where条件,来猜测返回的记录数大概是多少,从而判断应该采用怎样的访问路径。很明显,这是一定要参照具体的where条件里的值才能进行猜测的。这样就与节省CPU的初衷产生了矛盾,因为节省CPU的关键是使用绑定变量,你一旦使用了绑定变量,则oracle岂不是不知道你具体的字面值了吗?

        为了解决这一问题,oracle引入了绑定变量窥视。所谓绑定变量窥视,就是指oracle在第一次解析SQL语句的时候(也就是说该SQL第一次传入shared pool),会将你输入的绑定变量的值带入SQL语句里,从而参考你的字面值来猜测该SQL大概会返回多少条记录,从而得到优化的执行计划。然后,以后再次执行相同的SQL语句时,不再考虑你所输入的绑定变量的值,直接取出第一次生成的绑定变量。

        但是,很可惜的是,使用绑定变量从而共享游标与SQL优化是两个矛盾的目标。Oracle使用绑定变量的前提,是oracle认为大部分的列的数据都是分布比较均匀的。从而,使用第一次的绑定变量的值所得到的执行计划,大多数情况下都能适用于该绑定变量的其他的值。很明显,如果第一次传入的绑定变量的值恰好占整个数据量的百分比较高,从而导致全表扫描的执行计划。而后来传入的绑定变量的值都占整个数据量的百分比都很低,则应该走索引扫描会更好的,但是由于使用了绑定变量,从而oracle并不会再去看你的绑定变量的值,而是直接拿全表扫描的执行计划来用。这时,由于使用了绑定变量,虽然我们达到了游标共享,从而节省CPU的目的,但是SQL的执行计划却不够优化了。

        那么我们如何在绑定变量和SQL优化之间进行取舍呢?在OLTP应用中,由于并发性较高,CPU上的争用会比较严重,同时SQL本身执行时间较短,涉及到的数据量较少,解析所占的时间在整个SQL执行时间中占的比例较高,而花在I/O上的时间占的比例较低。因此尽管绑定变量会有SQL不够优化的问题,还是建议使用绑定变量。但是在DSS应用和数据仓库应用中,由于并发性较低,CPU上的争用较轻,同时SQL语句的执行时间都很长,而且主要时间花在等待I/O上,而解析占的比重较低,这时优化SQL执行计划的重要性就体现出来了。因此,建议不要使用绑定变量,而直接使用字面值。但是大多数的情况都是混合应用,既有OLTP又有数据仓库,这时就很难完美的解决该问题了。

        我们先来看一下11g之前的绑定变量窥视是如何工作的,以10g为例。

        我们先创建一个表,使得其含有的数据分布不均匀,并在该表上创建一个索引。

         hr@ora10g > create table t1 as select object_id as id,object_name from dba_objects;
        hr@ora10g > update t1 set id=1 where rownum        hr@ora10g > commit;
        hr@ora10g > create index idx_t1 on t1(id);

        这样,该表里id为的1记录有一万条,而id为其他值的记录都只有一条。从而,我们构建出一个分布不均匀的测试用表。然后,我们收集一下统计信息。注意,这里要收集直方图,为的是要让CBO知道id列上的数据分布不均匀。

         hr@ora10g> begin
        2 dbms_stats.gather_table_stats(
        3 user,
        4 't1',
        5 cascade => true,
        6 method_opt => 'for columns id size 254'
        7 );
        8 end;
        9 /

        我们找到表t1里最大的id,然后以该id作为第一个绑定变量传入,可以想象,该绑定变量将导致走索引。注意,我们这里设定的优化器目标为all_rows。

         hr@ora11g > select max(id) from t1;
        MAX(ID)
        ----------
        13871
        hr@ora10g> alter system flush shared_pool;
        hr@ora10g> var v_id number;
        hr@ora10g> var v_sql_id varchar2(20);
        hr@ora10g> exec :v_id := 13871;
        hr@ora10g> select * from t1 where id=:v_id;
        此处省略查询结果
        hr@ora10g > begin
        2 select sql_id into :v_sql_id from v$sql
        3 where sql_text like 'select * from t1 where id=:v_id%';
        4 end;
        5 /
        hr@ora10g > select * from table(dbms_xplan.display_cursor(:v_sql_id));
        PLAN_TABLE_OUTPUT
        --------------------------------------------------------------------------------
        SQL_ID djwq30cpbcz7k, child number 0
        -------------------------------------
        select * from t1 where id=:v_id
        Plan hash value: 50753647
        --------------------------------------------------------------------------------
        | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
        --------------------------------------------------------------------------------
        | 0 | SELECT STATEMENT | | | | 11 (100) |
        | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1365 | 28665| 11 (0) | 00:00:01
        |* 2 | INDEX RANGE SCAN | IDX_T1 | 1365 | | 3 (0) | 00:00:01
        --------------------------------------------------------------------------------
        ......
        hr@ora10g> exec :v_id := 1;
        hr@ora10g> select * from t1 where id=:v_id;
        此处省略查询结果
        hr@ora10g > begin
        2 select sql_id into :v_sql_id from v$sql
        3 where sql_text like 'select * from t1 where id=:v_id%';
        4 end;
        5 /
        hr@ora10g > select * from table(dbms_xplan.display_cursor(:v_sql_id));
        PLAN_TABLE_OUTPUT
        --------------------------------------------------------------------------------
        SQL_ID djwq30cpbcz7k, child number 0
        -------------------------------------
        select * from t1 where id=:v_id
        Plan hash value: 50753647
        --------------------------------------------------------------------------------
        | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
        --------------------------------------------------------------------------------
        | 0 | SELECT STATEMENT | | | | 11 (100) |
        | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1365 | 28665| 11 (0) | 00:00:01
        |* 2 | INDEX RANGE SCAN | IDX_T1 | 1365 | | 3 (0) | 00:00:01
        --------------------------------------------------------------------------------

        从上面结果可以看出,在为绑定变量传入第一个值为13871时,由于返回的记录条数较少,导致走索引扫描。当我们第二次传入绑定变量值1时,oracle不再生成新的执行计划,而直接拿索引扫描的执行路径来用。

        但是,如果先传入1的绑定变量值,然后再传入13871的绑定变量值时,会怎样?我们继续测试。

         hr@ora10g> alter system flush shared_pool;
        hr@ora10g> set autotrace traceonly exp stat;
        hr@ora10g> exec :v_id := 1;
        hr@ora10g> select * from t1 where id=:v_id;
        hr@ora10g > begin
        2 select sql_id into :v_sql_id from v$sql
        3 where sql_text like 'select * from t1 where id=:v_id%';
        4 end;
        5 /
        hr@ora10g > select * from table(dbms_xplan.display_cursor(:v_sql_id));
        PLAN_TABLE_OUTPUT
        --------------------------------------------------------------------------------
        SQL_ID djwq30cpbcz7k, child number 0
        -------------------------------------
        select * from t1 where id=:v_id
        Plan hash value: 3617692013
        --------------------------------------------------------------------------
        | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
        --------------------------------------------------------------------------
        | 0 | SELECT STATEMENT | | | | 13 (100)| |
        |* 1 | TABLE ACCESS FULL | T1 | 8738 | 179K | 13 (0) | 00:00:01 |
        --------------------------------------------------------------------------
        ......
        hr@ora10g > exec :v_id := 13871;
        hr@ora10g > select * from t1 where id=:v_id;
        hr@ora10g > begin
        2 select sql_id into :v_sql_id from v$sql
        3 where sql_text like 'select * from t1 where id=:v_id%';
        4 end;
        5 /
        hr@ora10g > select * from table(dbms_xplan.display_cursor(:v_sql_id));
        PLAN_TABLE_OUTPUT
        --------------------------------------------------------------------------------
        SQL_ID djwq30cpbcz7k, child number 0
        -------------------------------------
        select * from t1 where id=:v_id
        Plan hash value: 3617692013
        --------------------------------------------------------------------------
        | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
        --------------------------------------------------------------------------
        | 0 | SELECT STATEMENT | | | | 13 (100)| |
        |* 1 | TABLE ACCESS FULL | T1 | 8738 | 179K | 13 (0) | 00:00:01 |
        --------------------------------------------------------------------------

        很明显,先传入1的绑定变量时将导致生成的执行计划走全表扫描。后面传入的13871的绑定变量的最佳执行路径应该是索引扫描,但是由于CBO并不知道这一点,而是直接拿第一次生成的执行计划来用了,于是也走全表扫描了。

[1] [2] 

Oracle11g新特性之动态变量窥视

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
PHP 8.3发布:新特性一览PHP 8.3发布:新特性一览Nov 27, 2023 pm 12:52 PM

PHP8.3发布:新特性一览随着技术的不断发展和需求的不断变化,编程语言也在不断更新和改进。作为一种广泛应用于网络开发的脚本语言,PHP一直在不断进步,为开发者提供更强大和高效的工具。最近发布的PHP8.3版本带来了许多期待已久的新特性和改进,下面让我们来看一下这些新特性的一览。非空属性的初始化在过去的PHP版本中,如果一个类的属性没有被明确赋值,它的值

学习PHP8的新特性,深入理解最新技术的指南学习PHP8的新特性,深入理解最新技术的指南Dec 23, 2023 pm 01:16 PM

深入解析PHP8的新特性,助您掌握最新技术随着时间的推移,PHP编程语言一直在不断演进和改进。最近发布的PHP8版本为开发者提供了许多令人兴奋的新特性和改进,为我们的开发工作带来了更多便利和效率。在本文中,我们将深入解析PHP8的新特性,并提供具体的代码示例,旨在帮助您更好地掌握这些最新的技术。JIT编译器PHP8引入了JIT(Just-In-Time)编

php8有什么新特性php8有什么新特性Sep 25, 2023 pm 01:34 PM

php8新特性有JIT 编译器、类型推导、命名参数、联合类型、属性、错误处理改进、异步编程支持、新的标准库函数和匿名类的扩展等。详细介绍:1、JIT编译器,PHP8引入了JIT编译器,这是一个重要的性能改进,JIT编译器可以对一些高频执行的代码进行实时编译和优化,从而提高运行速度;2、类型推导,PHP8引入了类型推导功能,允许开发者在声明变量时自动推导出变量的类型等等。

PHP8.1引入的新的Redis扩展PHP8.1引入的新的Redis扩展Jul 07, 2023 pm 09:41 PM

PHP8.1引入的新的Redis扩展随着互联网的快速发展,大量的数据需要进行存储和处理。为了提高数据处理的效率和性能,缓存成为了一个不可或缺的部分。而在PHP开发中,Redis作为一种高性能的键值对存储系统,被广泛应用于缓存和数据存储的场景。为了进一步提升Redis在PHP中的使用体验,PHP8.1引入了新的Redis扩展,本文将介绍这一扩展的新增功能,并给

CSS3的新特性一览:如何使用CSS3实现过渡效果CSS3的新特性一览:如何使用CSS3实现过渡效果Sep 09, 2023 am 11:27 AM

CSS3的新特性一览:如何使用CSS3实现过渡效果CSS3作为CSS的最新版本,在众多新特性中,最有趣和实用的应该是过渡效果(transition)。过渡效果可以让我们的页面在交互时更加平滑、漂亮,给用户带来良好的视觉体验。本文将介绍CSS3过渡效果的基本用法,并附带相应的代码示例。transition-property属性:指定需要过渡的CSS属性过渡效果

go语言有什么新特性go语言有什么新特性Aug 24, 2023 pm 01:36 PM

go语言的新特性有:1、Go模块,用于管理Go语言项目的依赖关系;2、错误处理,增加了一个新的错误类型error,使得错误处理更加灵活和简洁;3、上下文包,用于在goroutine之间传递请求范围的值;4、嵌入,即一个结构体可以嵌入到另一个结构体中;5、同步包,更好地控制goroutine之间的同步和通信;6、错误值,更好地区分不同类型的错误;7、泛型,让开发者编写更灵活。

CSS3的新特性一览:如何使用CSS3实现水平居中布局CSS3的新特性一览:如何使用CSS3实现水平居中布局Sep 09, 2023 pm 04:09 PM

CSS3的新特性一览:如何使用CSS3实现水平居中布局在网页设计和布局中,水平居中布局是一项常见的需求。过去,我们经常使用复杂的JavaScript或CSS技巧实现此目的。然而,CSS3引入了一些新的特性,使得水平居中布局更加简单和灵活。本文将介绍一些CSS3的新特性,并提供一些代码示例,演示如何使用CSS3实现水平居中布局。一、使用flexbox布局fle

PHP8底层开发原理解密:利用新特性提高代码性能和可靠性PHP8底层开发原理解密:利用新特性提高代码性能和可靠性Sep 10, 2023 pm 04:25 PM

PHP8作为最新版本的PHP编程语言,引入了许多新的特性和改进,在底层开发原理方面做了一些重要的改变。本文将深入探讨PHP8的底层开发原理,并分析如何利用新特性提高代码性能和可靠性。首先,我们来了解一下PHP8的一些重要的底层开发原理。PHP8引入了JIT(Just-In-Time)编译器,这是一个动态编译器,可以将PHP代码即时转换为本地机器码,并在执行时

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기