日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Oracle优化09-绑定变量

發布時間:2025/3/21 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle优化09-绑定变量 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

思維導圖


系列博文

Oracle-綁定變量binding variable解讀

Oracle-Soft Parse/Hard Parse/Soft Soft Parse解讀


概述

綁定變量是OLTP系統中一個非常值得關注的技術點。良好的變量綁定會使OLTP系統數據庫中的SQL執行的飛快,內存效率極高。 不綁定變量有可能會使OLTP數據庫不堪負重,資源被SQL解析嚴重消耗,系統顯得緩慢。

本博文的案例基于Oracle Database 11g Enterprise Edition Release 11.2.0.4.0


SQL究竟是如何被執行的?

在介紹綁定變量之前,我們需要知道SQL究竟是如何被執行的?

當一個用戶與數據庫建立連接后,向數據庫發送SQL語句,Oracle在接到這條SQL后,首先會將這個SQL做一個Hash函數運算,得到一個Hash值,然后到共享池中尋找是否有和這個hash值匹配的SQL存在。

如果找到了,Oracle會直接使用已經存在的SQL的執行計劃去執行當前的SQL,然后將結果返回給用戶。

如果沒有找到,Oracle會認為這是一條新的SQL, 將會按照下面的順序來執行:


1 .語法分析

SQL 是否符Oracle規定的語法,如果有語法錯誤,則向用戶拋出錯誤信息


2. 語義分析

語法分析通過之后,Oracle會對這條SQL做一些對象、權限方面的檢查,查看SQL中操作的表是否存在,表中的列是否正確,用戶是否有權限操作這個對象的權限等


3 .生成執行計劃

這個過程Oracle在經過一些列的操作之后,來做出SQL最后的執行計劃,比如查看操作對象的統計信息,動態采樣等等。

如何生成執行計劃的詳細信息,可以參考10053事件


4.執行SQL

Oracle按照上一步生成的執行計劃,執行SQL,并將結果返回給用戶。


以上的這些工作,我們通常稱為硬分析(hard parse),其實是十分消耗系統資源的。 而對于相同Hash值的SQL已經存在于共享池中則稱為軟分析(soft parse)。


綁定變量 what ,why

綁定變量就起本質而言就是說把本來需要Oracle做硬分析的SQL變成了軟分析,以減少Oracle花費在SQL解析上的時間和資源。


是否采用綁定變量在資源消耗上對比

下面我們來對下同一條SQL被執行10000次,綁定變量和非綁定變量在資源消耗上的情況

采用綁定變量

打開SQL_TRACE

Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 Connected as xx@xgj##打開時間統計 SQL> set timing on;##為防止干擾信息,先手動的清空共享池中的信息(若生產環境慎重) SQL> alter system flush shared_pool;System alteredExecuted in 0.078 seconds##建表 SQL> create table t as select * from dba_objects; Table createdExecuted in 0.281 seconds##設置trace文件標識 SQL> alter session set tracefile_identifier='xgj_var_bind';Session alteredExecuted in 0 seconds##打開SQL_TRACE SQL> alter session set sql_trace=true;Session alteredExecuted in 0.015 seconds##執行SQL塊 SQL> begin2 for i in 1 .. 10000 loop3 execute immediate 'select * from t where t.object_id = :i' using i ;4 end loop;5 end;6 /PL/SQL procedure successfully completedExecuted in 0.578 seconds##關閉SQL_TRACE SQL> alter session set sql_trace=false ;Session alteredExecuted in 0 secondsSQL>

對原始trace文件進行tkprof分析匯總

在Oracle服務器端獲取到trace文件后,使用tkprof進行分析匯總,查看

oracle@entel1:[/oracle/diag/rdbms/cc/cc/trace]$ls *xgj_var_bind* cc_ora_32363_xgj_var_bind.trc cc_ora_32363_xgj_var_bind.trmoracle@entel1:[/oracle/diag/rdbms/cc/cc/trace]$tkprof cc_ora_32363_xgj_var_bind.trc xgj_var_bind.txt sys=noTKPROF: Release 11.2.0.4.0 - Development on Sat Dec 17 21:13:11 2016Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.

我們截取分析匯總后的關鍵部分來看

整個過程加上產生的遞歸SQL,我們可以看到整個語句的:

ALL NON-RECURSIVE STATEMENTS + ALL RECURSIVE STATEMENTS

  • 執行時間(elapsed):0.48+0.10 = 0.58 (和剛才輸出的時間大致一致)
  • CPU時間(cpu):0.48+0.09=0.57
  • 分析次數(parse):8+2=10
  • 執行次數(execute):9+10017=10025

不采用綁定變量

SQL> set timing on ; SQL> alter session set tracefile_identifier='xgj_var_unbind';Session alteredExecuted in 0.016 seconds SQL> alter session set sql_trace=true;Session alteredExecuted in 0.016 seconds SQL> begin2 for x in 1 .. 10000 loop3 execute immediate 'select * from t where t.object_id ='||x;4 end loop;5 end;6 /PL/SQL procedure successfully completedExecuted in 16.672 seconds -----耗時很長SQL>

執行tkprof分析匯總

查看xgj_var_unbind.txt關鍵部分

………… 中間省略一萬萬字

可以看到 每一條都是hard parse,非常消耗系統資源,耗時很長。

同樣的我們統計下執行信息:

ALL NON-RECURSIVE STATEMENTS + ALL RECURSIVE STATEMENTS

  • 執行時間(elapsed):1.28+15.38 =16.66
  • CPU時間(cpu):1.22+15.31
  • 分析次數(parse): 3+20000
  • 執行次數(execute):4+20000

通過對比我們可以發現,在OLTP系統中,使用綁定變量的SQL資源消耗要與那遠少于未綁定變量SQL的資源消耗,SQL執行的次數越多,差距越明顯。

未綁定變量SQL的資源主要消耗在產生的遞歸SQL上,這些SQL主要是對SQL語句做hard parse時使用的。

試想,當一個數據庫有成千上萬甚至更多的用戶同時執行這樣的SQL,而ORACLE只做一次硬分析,后面相同的SQL只執行SQL的執行操作,勢必將大大減輕數據庫的資源開銷。

這就是綁定變量的由來,它并不神秘,不過是拿一個變量來代替謂詞常量,讓ORACLE每次對用戶發送的SQL做hash運算,運算出相同的hash值,于是Oracle便將這些SQL看做同一個SQL對待而已。


OLTP和OLAP系統中是否需要綁定變量分析

如果你使用Oracle的圖形化工具DBCA創建數據庫,應該有印象,其中有一步是要求你選擇數據庫的類型是OLTP還是OLAP。 其實這就說明了OLTP和OLAP數據庫是有很大的差異的,Oracle需要知道你選擇的系統架構,以便于按照系統的架構對相應的參數值做設定,比如初始化參數。

OLTP和OLAP的請參考之前梳理的文章 Oracle-OLAP和OLTP解讀
http://blog.csdn.net/yangshangwei/article/details/52949378


OLTP栗子

數據:

SQL> drop table t;Table droppedSQL> create table t as select a.OBJECT_ID ,a.OBJECT_NAME from dba_objects a ;Table createdSQL> select count(1) from t;COUNT(1) ----------35234SQL> 循環300次,寫入更多的數據 每50次提交一次數據 SQL> begin2 for i in 1 .. 300 loop3 execute immediate 'insert into t select a.OBJECT_ID ,a.OBJECT_NAME from dba_objects a';4 if mod(i,50)=0 then5 commit;6 end if;7 end loop;8 end;9 /PL/SQL procedure successfully completedSQL> select count(1) from t;COUNT(1) ----------10605434SQL> 在object_id字段上創建索引 SQL> create index idx_t on t(object_id);Index created

操作步驟

SQL> alter session set tracefile_identifier='xgj_oltp';Session alteredSQL> alter session set sql_trace =true;Session altered執行兩遍SQL ##強制走全表掃描執行計劃 SQL> select /*+ full(t)*/ * from t where object_id = 188;OBJECT_ID OBJECT_NAME ---------- ---------------------188 SQLLOG$_PKEY...........301 rows selected##讓Oracle自己選擇執行計劃 SQL> select * from t where t.object_id = 188;OBJECT_ID OBJECT_NAME ---------- ---------------------188 SQLLOG$_PKEY...........301 rows selectedSQL> alter session set sql_trace=false;Session altered

tkprof匯總分析

可以看到 全表掃描執行計劃的SQL掃描過的數據塊明顯大于使用索引執行的SQL計劃。

從trace文件中可以看到,在fetch階段,全表掃描讀取了42093多個數據塊,而走索引的,在fetch階段,僅僅讀取了308個數據塊。


OLAP栗子

OLAP系統在SQL的操作中就復雜的多,OLAP數據庫上大多數的時候運行是一些報表SQL,這些SQL經常會用到聚合查詢(比如group by),而且結果集也是非常龐大,在這種情況下,索引并不是必然的選擇,甚至有些時候全表掃描的性能會由于索引,即使相同的SQL,如果謂詞條件不同,執行計劃都可能不同

數據

SQL> create table t2(object_id, object_name) partition by range (object_id)2 (partition p1 values less than (5000),3 partition p2 values less than (15000),4 partition p3 values less than (25000),5 partition p4 values less than (maxvalue))6 as select object_id, object_name from dba_objects;Table createdSQL> SQL> begin2 for x in 1 .. 300 loop3 insert into t2 select object_id ,object_name from dba_objects ;4 if mod(x,50)=0 then5 commit;6 end if;7 end loop;8 end;9 /PL/SQL procedure successfully completedSQL> select count(1) from t2;COUNT(1) ----------10609046SQL> select count(1) from t2 partition(p1);COUNT(1) ----------1504097SQL> select count(1) from t2 partition(p2);COUNT(1) ----------2691241SQL> select count(1) from t2 partition(p3);COUNT(1) ----------0SQL> select count(1) from t2 partition(p4);COUNT(1) ----------6413708SQL> 在分區表上建立本地索引 SQL> create index idx_t_id on t2(object_id) local;Index created##對表做一次分析(cascade => true ,索引也會被一同分析) SQL> exec dbms_stats.gather_table_stats(user,'t2',cascade => true);PL/SQL procedure successfully completed

操作步驟

我們使用如下命令

注釋:以上的命令,是在plsql客戶端執行的,可以支持, 但是autotrace命令,plsql并沒有很好的支持,所以我登錄到了服務器所在的主機執行的,當然也可以通過sqlplus客戶端操作。

SQL> set autotrace traceonly explain ;

從結果中我們可以看到,雖然只是謂詞的不同,但是oracle卻選擇了不同的執行計劃,因為Oracle認為那樣的計劃代價最小。


結論

  • OLAP系統完全沒有必要設置綁定變量那樣只會帶來負面的影響,比如導致SQL選擇了錯誤的執行計劃,讓Oracle對每條SQL做hard parse ,確切知道謂詞條件的值,這對執行計劃的選擇至關重要。 這是因為在OLAP系統中,SQL硬分析的代價是可以忽略的,系統的資源基本上是用于做大的SQL查詢,和查詢比較起來,SQL解析消耗的資源顯然微不足道,所以得到一個最優的執行計劃變得尤為重要
  • 在OLAP系統上,讓Oracle確切知道謂詞條件的值,它直接決定了SQL執行計劃的選擇,這樣做的方式就是不要綁定變量
  • 在OLAP系統中,表索引的分析顯得至關重要,因為它是Oracle為SQL做出正確的執行計劃的信息來源和一句。

  • bind peeking

    談到變量綁定,我們不得不提一下從Oracle9i開始引入的一個新的特性,叫做bind peaking ,顧名思義,就是在SQL語句硬解析的時候,Oracle會看一下當前SQL謂詞的值,以便于生成最佳的執行計劃。

    需要強調的是,bind peaking 只發生在hard parse的時候,即SQL被第一次執行的時候,之后的變量將不會再做peeking.

    bind peeking 并不能最終解決不同謂詞導致不同執行計劃的問題,它只能讓SQL第一次執行的時候,執行計劃更加準確,并不能幫助OLAP系統解決綁定變量導致執行計劃選擇錯誤的問題,所以,OLAP依然不應該使用綁定變量。

    對于OLTP系統來講,相同的SQL重復頻率非常搞,如果優化器范湖解析SQL,勢必極大地消耗資源。 另外OLTP系統用戶請求的結果通常都是非常小,說基本上都會考慮使用索引。 bind peeking在第一次hard parse的時候獲得了一個正確的執行計劃,后面的SQL都按照這個計劃來執行,可以極大地改善系統的性能,這是由OLTP系統的特性決定的。

    總結

    以上是生活随笔為你收集整理的Oracle优化09-绑定变量的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。