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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Oracle编程入门经典 第6章 在Oracle中处理语句

發布時間:2025/3/21 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle编程入门经典 第6章 在Oracle中处理语句 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

6.1???? SQL語句類別

  • DDL:數據定義語言語句。這樣的語句有CREATE、TRUNCATE和ALTER,它們用于建立數據庫中的結構,設置許可等。用戶可以使用它們維護Oracle數據詞典。
  • DML:數據操作語言語句。這些語句可以修改或者訪問信息,包括INSERT、UPDATE和DELETE。
  • 查詢:這是用戶的標準SELECT語句。查詢是指那么返回數據但是不修改數據的語句,是DML語句的子集。

6.2???? 怎樣執行語句

相對于查詢和DML語句,DDL更像是Oracle的一個內部命令。它不是在一些表上生成的查詢,而是完成一些工作的命令。例如,如果用戶使用:

Create table t(x int primary key, y date);

然而有意思的是,CREATE TABLE語句也可以在其中包含SELECT。我們可以使用:

Create table t as select * from scott.emp;

就像DML可以包含查詢一樣,DDL也可以這樣做。當DDL包含查詢的時候,查詢部分會像任何其它查詢一樣接受處理。Oracle執行這些語句的4個步驟,它們是:

  • 解析
  • 優化
  • 行源生成
  • 執行語句

對于DDL,通常實際上只會應用第一個和最后一個步驟,它將會解析語句,然后執行它。“優化”CREATE語句毫無意義(只有一種方法可以建立內容),也不需要建立一般的方案(建立表的過程眾所周知,已經在Oracle中直接編碼)。應該注意到,如果CREATE語句包含了查詢,那么就會按照處理其它查詢的方式處理這個查詢——采用以上所有步驟。

6.2.1????????? 解析

這是Oracle中任何語句處理過程的第一個步驟。解析(parsing)是將已經提交的語句分解,判定它是哪種類型的語句(查詢、DML或者DDL),并且在其上執行各種檢驗操作。

解析過程會執行三個主要的功能:

  • 語法檢查。這個語句是正確表述的語句么?它符合SQL參考手冊中記錄的SQL語法么?它遵循SQL的所有規則么?
  • 語義分析。這個語句是否正確參照了數據庫中的對象,它所引用的表和列存在么?用戶可以訪問這些對象,并且具有適當的特權么?語句中有歧義么?。
  • 檢查共享池。這個語句是否已經被另外的會話處理?

以下便是語法錯誤:

SQL> select from where 2;select from where 2*ERROR 位于第 1 行:ORA-00936: 缺少表達式

總而言之,如果賦予正確的對象和特權,語句就可以執行,那么用戶就遇到了語義錯誤;如果語句不能夠在任何環境下執行,那么用戶就遇到了語法錯誤。

解析操作中的下一步是要查看我們正在解析的語句是否牽線 些會話處理過。如果處理過,那么我們就很幸運,因為它可能已經存儲于共享池。在這種情況下,就可以執行軟解析(soft parse),換句話說,可以避免優化和查詢方案生成階段,直接進入執行階段。這將極大地縮短執行查詢的過程。另一方面,如果我們必須對查詢進行解析、優化和生成執行方案,那么就要執行所謂的硬解析(hard parse)。這種區別十分重要。當開發應用的時候,我們會希望有非常高的比例的查詢進行軟解析,以跳過優化/生成階段,因為這些階段非常占用CPU。如果我們必須硬解析大量的查詢,那么系統就會運行得非常緩慢。

  • Oracle怎樣使用共享池

  • 正如我們已經看到的,當Oracle解析了查詢,并且通過了語法和語義檢查之后,就會查看SGA的共享池組件,來尋找是否有另外的會話已經處理過完全相同的查詢。為此,當Oracle接收到我們的語句之后,就會對其進行散列處理。散列處理是獲取原始SQL文本,將其發往一下函數,并且獲取一個返回編號的過程。如果我們訪問一些V$表,就可以實際看到這些V$表在Oracle中稱為動態性能表(dynamic performance tables),服務器會在那里為我們存儲一些有用的信息。

    可能通過如下方式實現訪問V$表:

    為用戶賬號賦予SELECT_CATALOG_ROLE

    使用另一個具有SELECT_CATALOG_ROLE的角色(例如DBA)

    如果用戶不能訪問V$表以及V$SQL視圖,那么用戶就不能完成所有的“試驗”,但是掌握所進行的處理非常容易。

    試驗:觀察不同的散列值

    (1)??? 首先,我們將要執行2個對大家來講意圖和目的都相同的查詢:

    SQL> select * from dual;D-XSQL> select * from DUAL;D-X

    (2)??? 我們可以查詢動態性能視圖V$SQL來查看這些內容,它可以向我們展示剛才運行的2個查詢的散列值:

    SQL> select sql_text,hash_value from v$sql2 where upper(sql_text)='SELECT * FROM DUAL';SQL_TEXT------------------------------------------------ HASH_VALUE----------select * from DUAL1708540716select * from dual4035109885

    通常不需要實際查看散列值,因為它們在Oracle內部使用。當生成了這些值之后,Oracle就會在共享池中進行搜索,尋找具有相同散列值的語句。然后將它找到的SQL_TEXT與用戶提交的SQL語句進行比較,以確保共享池中的文本完全相同。這個比較步驟很重要,因為散列函數的特性之一就是2個不同的字符串也可能散列為相同的數字。

    注意:

    散列不是字符串到數字的唯一映射。

    總結到目前為止我們所經歷的解析過程,Oracle已經:

    • 解析了查詢
    • 檢查了語法
    • 驗證了語義
    • 計算了散列值
    • 找到了匹配
    • 驗證與我們的查詢完全相同的查詢(它引用了相同的對象)

    在Oracle從解析步驟中返回,并且報告已經完成軟解析之前,還要執行最后一項檢查。最后的步驟就是要驗證查詢是否是在相同的環境中解析。環境是指能夠影響查詢方案生成的所有會話設置,例如SORT_AREA_SIZE或者OPTIMIZER_MODE。SORT_AREA_SIZE會通知Oracle,它可以在不使用磁盤存儲臨時結果的情況下,為排序數據提供多少內存。圈套的SORT_AREA_SIZE會生成與較小的設置不同的優化查詢方案。例如,Oracle可以選擇一個排序數據的方案,而不是使用索引讀取數據的方案。OPTIMIZER_MODE可以通知Oracle實際使用的優化器。

    SQL> alter session set OPTIMIZER_MODE=first_rows;會話已更改。SQL> select * from dual;D-XSQL> select sql_text,hash_value,parsing_user_id2 from v$sql3 where upper(sql_text)='SELECT * FROM DUAL'4 /SQL_TEXT------------------------------------------------- HASH_VALUE PARSING_USER_ID---------- ---------------select * from DUAL1708540716 5select * from dual4035109885 5select * from dual4035109885 5

    這2個查詢之間的區別是第一個查詢使用默認的優化器(CHOOSE),剛才執行的查詢是在FIRST_ROWS模式中解析。

    SQL> select sql_text,hash_value,parsing_user_id,optimizer_mode2 from v$sql3 where upper(sql_text)='SELECT * FROM DUAL'4 /SQL_TEXT-------------------------------------------------------------- HASH_VALUE PARSING_USER_ID OPTIMIZER_---------- --------------- ----------select * from DUAL1708540716 5 CHOOSEselect * from dual4035109885 5 CHOOSEselect * from dual4035109885 5 FIRST_ROWS

    在這個階段的最后,當Oracle完成了所有工作,并且找到了匹配查詢,它就可以從解析過程中返回,并且報告已經進行了一個軟解析。我們無法看到這個報告,因為它由Oracle在內部使用,來指出它現在完成了解析過程。如果沒有找到匹配查詢,就需要進行硬解析。

    6.2.2????????? 優化

    當重用SQL的時候,可以路過這個步驟,但是每個特有的查詢/DML語句都要至少實現一次優化。

    優化器的工作表面上看起來簡單,它的目標就是找到最好的執行用戶查詢的途徑,盡可能地優化代碼。盡管它的工作描述非常簡單,但是實際上所完成的工作相當復雜。執行查詢可能會有上千種的方式,它必須找到最優的方式。為了判斷哪一種查詢方案最適合:Oracle可能會使用2種優化器:

    • 基于規則的優化器(Rule Based Optimizer,RBO)——這種優化器基于一組指出了執行查詢的優選方法的靜態規則集合來優化查詢。這些規則直接編入了Oracle數據庫的內核。RBO只會生成一種查詢方案,即規則告訴它要生成的方案。
    • 基于開銷的優化器(Cost Based Optimizer,CBO)——這種優化器人基于所收集的被訪問的實際數據的統計數據來優化查詢。它在決定最優方案的時候,將會使用行數量、數據集大小等信息。CBO將會生成多個(可能上千個)可能的查詢方案,解決查詢的備選方式,并且為每個查詢方案指定一個數量開銷。具有最低開銷的查詢方案將會被采用。

    OPTIMIZER_MODE是DBA能夠在數據庫的初始化文件中設定的系統設置。默認情況下,它的值為CHOOSE,這可以讓Oracle選取它要使用的優化器(我們馬上就會討論進行這種選擇的規則)。DBA可以選擇覆蓋這個默認值,將這個參數設置為:

    • RULE:規定Oracle應該在可能情況下使用RBO。
    • FIRST_ROWS:Oracle將要使用CBO,并且生成一個盡可能快地獲取查詢返回的第一行的查詢方案。
    • ALL_ROWS:Oracle將要使用CBO,并且生成一個盡可能快地獲取查詢所返回的最后一行(也就獲得所有的行)的查詢方案。

    正如我們在上面看到的,可以通過ALTER SESSION命令在會話層次覆寫這個參數。這對于開發者希望規定它們想要使用的優化器以及進行測試的應用都非常有用。

    現在,繼續討論Oracle怎樣選擇所使用的優化器,及其時機。當如下條件為真的時候,Oracle就會使用CBO:

    • 至少有一個查詢所參考的對象存在統計數據,而且OPTIMIZER_MODE系統或者會話參數沒有設置為RULE。
    • 用戶的OPTIMIZER_MODE系統/會話參數設置為RULE或者CHOOSE以外的值。
    • 用戶查詢要訪問需要CBO的對象,例如分區表或者索引組織表。
    • 用戶查詢包含了RULE提示(hint)以外的其它合法提示。
    • 用戶使用了只有CBO才能夠理解的特定的SQL結構,例如CONNECT BY。

    目前,建議所有的應用都使用CBO。自從Oracle第一次發布就已經使用的RBO被認為是過時的查詢優化方法,使用它的時候很多新特性都無法利用。例如,如果用戶想要使用如下特性的時候,就不能夠使用RBO:

    • 分區表
    • 位圖索引
    • 索引組織表
    • 規則的細粒度審計
    • 并行查詢操作
    • 基于函數的索引

    CBO不像RBO那樣容易理解。根據定義,RBO會遵循一組規則,所以非常容易預見結果。而CBO會使用統計數據來決定查詢所使用的方案。

    為了分析和展示這種方法,可以使用一個簡單的救命。我們將會在SQL*Plus中,從SCOTT模式復制EMP和DEPT表,并且向這些表增加主鍵/外鍵。將會使用SQL*Plus產品中內嵌工具AUTOTRACE,比較RBO和CBO的方案。

    試驗:比較優化器

    (1)??? 用戶確保作為SCOTT以外的其它用戶登錄到數據庫上,然后使用CREATE TABLE命令復制SCOTT.EMP和SCOTT.DEPT表:

    SQL> create table emp2 as3 select * from scott.emp;表已創建。SQL> create table dept2 as3 select * from scott.dept;表已創建。

    (2)??? 向EMP和DEPT表增加主鍵

    SQL> alter table emp2 add constraint emp_pk primary key(empno);表已更改。SQL> alter table dept2 add constraint dept_pk primary key(deptno);表已更改。

    (3)??? 添加從EMP到DEPT的外鍵

    SQL> alter table emp2 add constraint emp_fk_dept3 foreign key(deptno) references dept;表已更改。

    (4)??? SQL*Plus中啟用AUTOTRACE工具。我們正在使用的AUTOTRACE命令會向我們展示Oracle可以用來執行查詢經過優化的查詢方案(它不會實際執行查詢):

    SQL> set autotrace traceonly explain

    如果啟動失敗,解決方法如下:

    SQL> set autotrace traceonly explainSP2-0613: 無法驗證 PLAN_TABLE 格式或實體SP2-0611: 啟用EXPLAIN報告時出錯

    解決方法:

    1.以當前用戶登錄

    SQL> connect zhyongfeng/zyf@YONGFENG as sysdba;已連接。

    2.運行utlxplain.sql(在windows的C:\oracle\ora92\rdbms\admin下),即創建PLAN_TABLE

    SQL> remSQL> rem $Header: utlxplan.sql 29-oct-2001.20:28:58 mzait Exp $ xplainpl.sqlSQL> remSQL> Rem Copyright (c) 1988, 2001, Oracle Corporation. All rights reserved. SQL> Rem NAMESQL> REM UTLXPLAN.SQLSQL> Rem FUNCTIONSQL> Rem NOTESSQL> Rem MODIFIEDSQL> Rem mzait 10/26/01 - add keys and filter predicates to the plan tableSQL> Rem ddas 05/05/00 - increase length of options columnSQL> Rem ddas 04/17/00 - add CPU, I/O cost, temp_space columnsSQL> Rem mzait 02/19/98 - add distribution method columnSQL> Rem ddas 05/17/96 - change search_columns to numberSQL> Rem achaudhr 07/23/95 - PTI: Add columns partition_{start, stop, id}SQL> Rem glumpkin 08/25/94 - new optimizer fieldsSQL> Rem jcohen 11/05/93 - merge changes from branch 1.1.710.1 - 9/24SQL> Rem jcohen 09/24/93 - #163783 add optimizer columnSQL> Rem glumpkin 10/25/92 - Renamed from XPLAINPL.SQLSQL> Rem jcohen 05/22/92 - #79645 - set node width to 128 (M_XDBI in gendef)SQL> Rem rlim 04/29/91 - change char to varchar2SQL> Rem Peeler 10/19/88 - CreationSQL> RemSQL> Rem This is the format for the table that is used by the EXPLAIN PLANSQL> Rem statement. The explain statement requires the presence of thisSQL> Rem table in order to store the descriptions of the row sources.SQL>SQL> create table PLAN_TABLE (2 statement_id varchar2(30),3 timestamp date,4 remarks varchar2(80),5 operation varchar2(30),6 options varchar2(255),7 object_node varchar2(128),8 object_owner varchar2(30),9 object_name varchar2(30),10 object_instance numeric,11 object_type varchar2(30),12 optimizer varchar2(255),13 search_columns number,14 id numeric,15 parent_id numeric,16 position numeric,17 cost numeric,18 cardinality numeric,19 bytes numeric,20 other_tag varchar2(255),21 partition_start varchar2(255),22 partition_stop varchar2(255),23 partition_id numeric,24 other long,25 distribution varchar2(30),26 cpu_cost numeric,27 io_cost numeric,28 temp_space numeric,29 access_predicates varchar2(4000),30 filter_predicates varchar2(4000));

    3.將plustrace賦給用戶(因為是當前用戶,所以這步可省略)

    SQL> grant all on plan_table to zhyongfeng;授權成功。

    4.通過執行plustrce.sql(C:\oracle\ora92\sqlplus\admin\ plustrce.sql),如下

    SQL> @C:\oracle\ora92\sqlplus\admin\plustrce.sql;

    會有以下結果:

    SQL> create role plustrace;角色已創建SQL>SQL> grant select on v_$sesstat to plustrace;授權成功。SQL> grant select on v_$statname to plustrace;授權成功。SQL> grant select on v_$session to plustrace;授權成功。SQL> grant plustrace to dba with admin option;授權成功。SQL>SQL> set echo off

    5.授權plustrace到用戶(因為是當前用戶,這步也可以省略)

    SQL> grant plustrace to zhyongfeng;授權成功。

    (5)??? 啟用了AUTORACE,在我們的表上運行查詢:

    SQL> set autotrace on;SQL> set autotrace traceonly explain;SQL> select * from emp,dept2 where emp.deptno=dept.deptno;Execution Plan----------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE1 0 NESTED LOOPS2 1 TABLE ACCESS (FULL) OF 'EMP'3 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'4 3 INDEX (UNIQUE SCAN) OF 'DEPT_PK' (UNIQUE)

    由于沒有收集任何統計信息(這是新建立的表),所以我們當前在這個例子中要使用RBO;我們無法訪問任何需要CBO的特殊對象,我們的優化器目標要設置為CHOOSE。我們也能夠從輸出中表明我們正在使用RBO。在這里,RBO優化器會選擇一個將要在EMP表上進行FULL SCAN的方案。為了執行連接,對于在EMP表中找到的每一行,它都會獲取DEPTNO字段,然后使用DEPT_PK索引尋找與這個DEPTNO相匹配的DEPT記錄。

    如果我們簡單分析已有的表(目前它實際上非常小),就會發現通過使用CBO,將會獲得一個非常不同的方案。

    注意:

    設置Autotrace的命令

    序號

    列名

    解釋

    1

    SET AUTOTRACE OFF

    此為默認值,即關閉Autotrace

    2

    SET AUTOTRACE ON

    產生結果集和解釋計劃并列出統計

    3

    SET AUTOTRACE ON EXPLAIN

    顯示結果集和解釋計劃不顯示統計

    4

    SETAUTOTRACE TRACEONLY

    顯示解釋計劃和統計,盡管執行該語句,但您將看不到結果集

    5

    SET AUTOTRACE TRACEONLY STATISTICS

    只顯示統計

    Autotrace執行計劃的各列的涵義

    序號

    列名

    解釋

    1

    ID_PLUS_EXP

    每一步驟的行號

    2

    PARENT_ID_PLUS_EXP

    每一步的Parent的級別號

    3

    PLAN_PLUS_EXP

    實際的每步

    4

    OBJECT_NODE_PLUS_EXP

    Dblink或并行查詢時才會用到

    AUTOTRACE Statistics常用列解釋

    序號

    列名

    解釋

    1

    db block gets

    從buffer cache中讀取的block的數量

    2

    consistent gets

    從buffer cache中讀取的undo數據的block的數量

    3

    physical reads

    從磁盤讀取的block的數量

    4

    redo size

    DML生成的redo的大小

    5

    sorts (memory)

    在內存執行的排序量

    6

    sorts (disk)

    在磁盤上執行的排序量

    (6)??? ANALYZE通常是由DBA使用的命令,可以收集與我們的表和索引有關的統計值——它需要被運行,以便CBO能夠具有一些可以參照的統計消息。我們現在來使用它:

    SQL> analyze table emp compute statistics;表已分析。SQL> analyze table dept compute statistics;表已分析。

    (7)??? 現在,我們的表已經進行了分析,將要重新運行查詢,查看Oracle這次使用的查詢方案:

    SQL> select * from emp,dept2 where emp.deptno=dept.deptno;Execution Plan----------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=5 Card=14 Bytes=700)1 0 HASH JOIN (Cost=5 Card=14 Bytes=700)2 1 TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=5 Bytes=90)3 1 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=14 Bytes=448)

    在這里,CBO決定在2個表進行FULL SCAN(讀取整個表),并且HASH JOIN它們。這主要是因為:

    • 我們最終要訪問2個表中的所有行
    • 表很小
    • 在小表中通過索引訪問每一行(如上)要比完全搜索它們慢

    ?

    工作原理

    CBO在決定方案的時候會考慮對象的規模。從RBO和CBO的AUTOTRACE輸出中可以發現一個有意思的現象是,CBO方案包含了更多的信息。在CBO生成的方案中,將會看到的內容有:

    • COST——賦予這個步驟的查詢方案的數量值。它是CBO比較相同查詢的多個備選方案的相對開銷,尋找具有最低整體開銷的方案時所使用的內部數值。
    • CARD——這個步驟的核心數據,換句話說,就是這個步驟將要生成的行的估計數量。例如,可以發現DEPT的TABLE ACCESS(FULL)估計要返回4條記錄,因為DEPT表只有4條記錄,所以這個結果很正確。
    • BYTES——方案中的這個步驟氣概生成的數據的字節數量。這是附屬列集合的平均行大小乘以估計的行數。

    用戶將會注意到,當使用RBO的時候,我們無法看到這個信息,因此這是一種查看所使用優化器的方法。

    如果我們“欺騙”CBO,使其認為這些表比它們實際的要大,就可以得到不同的規模和當前統計信息。

    試驗:比較優化器2

    為了完成這個試驗,我們將要使用稱為DBMS_STATS的補充程序包。通過使用這個程序包,就可以在表上設置任意統計(可能要完成一些測試工作,分析各種環境下的生成方案)。

    (1)??? 我們使用DBMS_STATS來欺騙CBO,使其認為EMP表具有1000萬條記錄,DEPT表具有100萬條記錄:

    SQL> begin2 dbms_stats.set_table_stats3 (user,'EMP',numrows=>10000000,numblks=>1000000);4 dbms_stats.set_table_stats5 (user,'DEPT',numrows=>1000000,numblks=>100000);6 end;7 /PL/SQL 過程已成功完成。

    (2)??? 我們將要執行與前面完全相同的查詢,查看新統計信息的結果:

    SQL> select * from emp,dept2 where emp.deptno=dept.deptno;Execution Plan----------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=79185 Card=2000000000000 Bytes=100000000000000)1 0 HASH JOIN (Cost=79185 Card=2000000000000 Bytes=100000000000000)2 1 TABLE ACCESS (FULL) OF 'DEPT' (Cost=6096 Card=1000000 Bytes=18000000)3 1 TABLE ACCESS (FULL) OF 'EMP' (Cost=60944 Card=10000000 Bytes=320000000)

    用戶可以發現,優化器選擇了完全不同于以前的方案。它不再散列這些明顯很大的表,而是會MERGE(合并)它們。對于較小的DEPT表,它將會使用索引排序數據,由于在EMP表的DEPTNO列上沒有索引,為了將結果合并在一起,要通過DEPTNO排序整個EMP。

    (3)??? 如果將OPTIMIZER_MODE參數設置為RULE,就可以強制使用RBO(即使我們有這些統計數據),可以發現它的行為是完全可以預期的:

    SQL> alter session set OPTIMIZER_MODE=RULE;會話已更改。SQL> select * from emp,dept2 where emp.deptno=dept.deptno;Execution Plan----------------------------------------------------------0 SELECT STATEMENT Optimizer=RULE1 0 NESTED LOOPS2 1 TABLE ACCESS (FULL) OF 'EMP'3 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'4 3 INDEX (UNIQUE SCAN) OF 'DEPT_PK' (UNIQUE)

    注意:

    無論附屬表中的數據數量如何,如果給定相同的數據對象集合(表和索引),RBO每次都會生成完全相同的方案。

    6.2.3????????? 行源生成器

    行源生成器是Oracle的軟件片段,它可以從優化器獲取輸出,并且將其格式化為的執行方案。例如,在這部分之前我們看到了SQL*Plus中的AUTOTRACE工具所生成的查詢方案。那個樹狀結構的方案就是行源生成器的輸出;優化器會生成方案,而行源生成器會將其轉換成為Oracle系統的其余部分可以使用的數據結構。

    6.2.4????????? 執行引擎

    執行引擎(execution engine)是獲取行源生成器的輸出,并且使用它生成結果集或者對表進行修改的進程。例如,通過使用以上最后生成的AUTOTRACE方案,執行引擎就可以讀取整個EMP表。它會通過執行INDEX UNIQUE SCAN讀取各行,在這個步驟中,Oracle會在DEPT_PK索引上搜索UNIQUE索引找到特定值。然后使用它所返回的值去尋找特定DEPTNO的ROWID(包含文件、數據文件、以及數據塊片段的地址,可以利用這個地址找到數據行)。然后它就可以通過ROWID訪問DEPT表。

    執行引擎是整個進程的骨干,它是實際執行所生成的查詢方案的部分。它會執行I/O,讀取數據、排序數據、連接數據以及在需要的時候在臨時表中存儲數據。

    6.2.5????????? 語句執行匯總

    在語句執行部分中,我們已經分析了為了進程處理,用戶提交給Oracle的語句氣概經歷的4個階段。圖6-1是匯總這個流程的流程圖:

    圖6-1 語句處理過程流圖

    當向Oracle提交SQL語句的時候,解析器就要確定它是需要進行硬解析還是軟解析。

    如果語句要進行軟解析,就可以直接進行SQL執行步驟,獲得輸出。

    如果語句必須要進行硬解析,就需要將其發往優化器,它可以使用RBO或者CBO處理查詢。當優化器生成它認為的最優方案之后,就會將方案轉遞給行源生成器。

    行源生成器會將優化器的結果轉換為Oracle系統其余部分能夠處理的格式,也就是說,能夠存儲在共享池中,并且被執行的可重復使用的方案。這個方案可以由SQL引擎使用,處理查詢并且生成答案(也就是輸出)。

    6.3???? 查詢全過程

    現在,我們來討論Oracle處理查詢的全過程。為了展示Oracle實現查詢過程的方式,我們將要討論2個非常簡單,但是完全不同的查詢。我們的示例要著重于開發者經常會問及的一個普通問題,也就是說:“從我的查詢中將會返回多少行數據?”答案很簡單,但是通常直到用戶實際獲取了最后一行數據,Oracle才知道返回了多少行。為了更好理解,我們將會討論獲取離最后一行很遠的數據行的查詢,以及一個必須等待許多(或者所有)行已經處理之后,可以返回記錄的查詢。

    對于這個討論,我們將要使用2個查詢:

    SELECT * FROM ONE_MILLION_ROW_TABLE;

    以及

    SELECT * FROM ONE_MILLION_ROW_TABLE ORDER BY C1;

    在這里,假定ONE_MILLION_ROW_TABLE是我們放入了100行的表,并且在這個表上沒有索引,它沒有采用任何方式排序,所以我們第二個查詢中的ORDYER BY要有很多工作去做。

    第一個查詢SELECT * FROM ONE_MILLION_ROW_TABLE將會生成一個非常簡單的方案,它只有一個步驟:

    TABLE ACCESS(FULL) OF ONE_MILLION_ROW_TABLE

    這就是說Oracle將要訪問數據庫,從磁盤或者緩存讀取表的所有數據塊。在掌擊的環境中(沒有并行查詢,沒有表分區),將會按照從第一個盤區到它的最后一個盤區讀取表。幸運的是,我們立即就可以從這個查詢中獲取返回數據。只要Oracle能夠讀取信息,我們的客戶應用就可以獲取數據行。這就是我們不能在獲得最后一行之前,確定查詢將會返回多少行的原因之一—甚至Oracle也不知道要返回多少行。當Oracle開始處理這個查詢的時候,它所知道的就是構成這個表的盤區,它并不知道這些盤區中的實際行數(它能夠基于統計進行猜測,但是它不知道)。在這里,我們不必等待最后一行接受處理,就可以獲取第一行,因此我們只有實際完成之后才能夠精確的行數量。

    第二個查詢會有一些不同。在大多數環境中,它都會分為2個步驟進行。首先是一個ONE_MILLION_ROW_TABLE的TABLE ACCESS(FULL)步驟,它人將結果反饋到SORT(ORDER BY)步驟(通過列C1排序數據庫)。在這里,我們將要等候一段時間才可以獲得第一行,因為在獲取數據行之前必須要讀取、處理并且排序所有的100萬行。所以這一次我們不能很快獲得第一行,而是要等待所有的行都被處理之后才行,結果可能要存儲在數據庫中的一些臨時段中(根據我們的SORT_AREA_SIZE系統/會話參數)。當我們要獲取結果時,它們將會來自于這些臨時空間。

    總而言之,如果給定查詢約束,Oracle就會盡可能快地返回答案。在以上的示例中,如果在C1上有索引,而且C1定義為NOT NULL,那么Oracle就可以使用這個索引讀取表(不必進行排序)。這就可以盡可能快地響應我們的查詢,為我們提供第一行。然后,使用這種過程獲得最后一行就比較慢,因為從索引中讀取100萬行會相當慢(FULL SCAN和SORT可能會更有效率)。所以,所選方案會依賴于所使用的優化器(如果存在索引,RBO總會傾向于選擇使用索引)和優化目標。例如,運行在默認模式CHOOSE中,或者使用ALL_ROWS模式的CBO將使用完全搜索和排序,而運行于FIRST_ROWS優化模式的CBO將可能要使用索引。

    6.4???? DML全過程

    現在,我們要討論怎樣處理修改的數據庫的DML語句。我們將要討論怎樣生成REDO和UNDO,以及怎樣將它們用于DML事務處理及其恢復。

    作為示例,我們將會分析如下事務處理會出現的情況:

    INSERT INTO T(X,Y) VALUES (1,1);UPDATE T SET X=X+1 WHERE X=1;DELETE FROM T WHERE X=2;

    最初對T進行的插入將會生成REDO和UNDO。如果需要,為了對ROLLBACK語句或者故障進行響應,所生成的UNDO數據將會提供足夠的信息讓INSERT“消失”。如果由于系統故障要再次進行操作,那么所生成的UNDO數據將會為插入“再次發生”提供足夠的信息。UNDO數據可能會包含許多信息。

    所以,在我們執行了以上的INSERT語句之后(還沒有進行UPDATE或者DELETE)。我們就會擁有一個如圖6-2所示的狀態。

    ?

    圖6-2 執行INSERT語句之后的狀態

    這里有一些已經緩存的,經過修改的UNDO(回滾)數據塊、索引塊,以及表數據塊。所有這些都存儲在數據塊緩存中。所有這些經過修改的數據塊都會由重做日志緩存中的表項保護。所有這些信息現在都受到緩存。

    現在來考慮一個在這個階段出現系統崩潰的場景。SGA會受到清理,但是我們實際上沒有使用這里列舉的項,所以當我們臭不可聞啟動的時候,就好像這個事務處理過程從來沒有發生過樣。所有發生改變的數據塊都沒有寫入磁盤,REDO信息也沒有寫入磁盤。

    在另一個場景中,緩存可能已經填滿。在這種情況下,DBWR必須要騰出空間,清理我們已經改變的數據塊。為了完成這項工作,DBWR首先會要求LGWR清理保護數據庫數據塊的REDO塊。

    注意:

    在DBWR將已經改變的數據塊定稿磁盤之前,LGWR必須清理與這些數據塊相關聯的REDO信息。

    在我們的處理過程中,這時要清理重做日志緩存(Oracle會反復清理這個緩存),緩存中的一些改變也要寫入磁盤。在這種情況下,即如圖6-3所示。

    ?

    圖6-3 清理重做日志緩存的狀態

    接下來,我們要進行UPDATE。這會進行大體相同的操作。這一次,UNDO的數據將會更大,我們會得到圖6-4所示情況。

    ?

    圖6-4 UPDATE圖示

    我們已經將更多的新UNDO數據塊增加到了緩存中。已經修改了數據庫表和索引數據塊,所以我們要能夠在需要的時候UNDO(撤銷)已經進行的UPDATE。我們還生成了更多的重做日志緩存表項。到目前為止,已經生成的一些重做日志表項已經存入了磁盤,還有一些保留在緩存中。

    現在,繼續DELETE。這里會發生大體相同的情況。生成UNDO,修改數據塊,將REDO發往重做日志緩存。事實上,它與UPDATE非常相似,我們要對其進行COMMIT,在這里,Oracle會將重做日志緩存清理到磁盤上,如圖6-5所示。

    ?

    圖6-5 DELETE操作后圖示

    有一些已經修改的數據塊保留在緩存中,還有一些可能會被清理到磁盤上。所有可以重放這個事務處理的REDO信息都會安全地放在磁盤上,現在改變已永久生效。

    6.5???? DDL處理

    最后,我們來討論Oracle怎樣處理DDL。DDL是用戶修改Oracle數據詞典的方式。為了建立表,用戶不能編寫INSERT INTO USER_TABLES語句,而是要使用CREATE TABLE語句。在后臺,Oracle會為用戶使用大量的SQL(稱為遞歸SQL,這些SQL會對其它SQL產生副作用)。

    執行DDL活動將會在DDL執行之前發出一個COMMIT,并且在隨后立即使用一個COMMIT或者ROLLBACK。這就是說,DDL會像如下偽碼一樣執行:

    COMMIT;DDL-STATEMENT;IF (ERROR) THENROLLBACK;ELSECOMMIT;END IF;

    用戶必須注意,COMMIT將要提交用戶已經處理的重要工作——即,如果用戶執行:

    INSERT INTO SOME_TABLE VALUES(‘BEFORE’);CREATE TABLE T(X INT );INSERT INTO SOME_TABLE VALUES(‘AFTER’);ROLLBACK;

    由于第一個INSERT已經在Oracle嘗試CREATE TABLE語句之前進行了提交,所以只有插入AFTER的行會進行回滾。即使CREATE TABLE失敗,所進行的BEFORE插入也會提交。

    6.6???? 小結

    • Oracle怎樣解析查詢、從語法和語義上驗證它的正確性。
    • 軟解析和硬解析。在硬解析情況下,我們討論了處理語句所需的附加步驟,也就是說,優化和行源生成。
    • Oracle優化器以及它的2種模式RULE和COST。
    • 用戶能夠怎樣在SQL*Plus中使用AUTOTRACE查看所使用的優化器模式。
    • Oracle怎樣使用REDO和UNDO提供故障保護。

    文章根據自己理解濃縮,僅供參考。

    摘自:《Oracle編程入門經典》 清華大學出版社?http://www.tup.com.cn/


    from:?http://www.cnblogs.com/yongfeng/archive/2013/01/19/2867809.html

    總結

    以上是生活随笔為你收集整理的Oracle编程入门经典 第6章 在Oracle中处理语句的全部內容,希望文章能夠幫你解決所遇到的問題。

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