您的統(tǒng)計(jì)信息是否陳舊?不要再等待了
?
??? 大部分DBA都知道,Oracle 10g 版本最后不再支持(而不是反對(duì))基于規(guī)則的優(yōu)化器 (RBO)。考慮到這種期待已久的發(fā)展即將發(fā)生,很多 Oracle9i 數(shù)據(jù)庫商店升級(jí)到基于開銷的優(yōu)化器 (CBO),以便進(jìn)入支持循環(huán)并利用查詢重寫和分區(qū)修剪等高級(jí)特性。但是,問題在于統(tǒng)計(jì)信息 — 或者說在于缺少統(tǒng)計(jì)信息。
?
??? 因?yàn)?CBO 依靠準(zhǔn)確的(或者說比較準(zhǔn)確的)統(tǒng)計(jì)信息來產(chǎn)生優(yōu)化的執(zhí)行路徑,所以 DBA 需要確保定期收集統(tǒng)計(jì)信息,創(chuàng)建另一個(gè)執(zhí)行核對(duì)清單。在 10g 之前,這一過程可能由于多種原因而徒勞無功。這種困難導(dǎo)致產(chǎn)生了一種理論,即 CBO 具有“自己的思想” — 這意味著會(huì)有隨意更改執(zhí)行路徑的行為!
?
??? 在 10g 中已經(jīng)消除了很多這類的顧慮,它能夠自動(dòng)收集統(tǒng)計(jì)信息。在 Oracle9i 中,您可以通過打開表監(jiān)視選項(xiàng) (ALTER TABLE ...MONITORING) 然后檢查這些表的視圖 DBA_TAB_MODIFICATIONS,檢查表中的數(shù)據(jù)是否已明顯更改過。
?
??? 在 10g 中,已不再使用 MONITORING 語句了。而通過設(shè)置初始化參數(shù) STATISTICS_LEVEL 為 TYPICAL 或 ALL,就可以自動(dòng)收集統(tǒng)計(jì)信息。(默認(rèn)值為 TYPICAL,因此可以隨即啟用自動(dòng)收集統(tǒng)計(jì)信息的功能。)Oracle 數(shù)據(jù)庫 10g 具有一個(gè)預(yù)定義的調(diào)度程序(您在第 19 周中已經(jīng)學(xué)習(xí)過調(diào)度程序)作業(yè),名稱為 GATHER_STATS_JOB,它由 STATISTIC_LEVEL 參數(shù)的適當(dāng)數(shù)值所激活。
?
??? 統(tǒng)計(jì)信息的收集是資源相當(dāng)密集的工作,因此您可能希望確保它不影響數(shù)據(jù)庫的正常操作。在 10g 中,您可以使這一工作自動(dòng)完成:可對(duì)一個(gè)名為 AUTO_TASK_CONSUMER_GROUP 的特定資源用戶組進(jìn)行預(yù)定義,用于自動(dòng)執(zhí)行一些任務(wù),比如收集統(tǒng)計(jì)信息。該用戶組確保這些統(tǒng)計(jì)信息收集作業(yè)的優(yōu)先權(quán)低于默認(rèn)用戶組,因此減少或消除了自動(dòng)化任務(wù)占用整個(gè)機(jī)器的風(fēng)險(xiǎn)。
?
??? 如果希望將參數(shù) STATISTIC_LEVEL 設(shè)為 TYPICAL 卻不希望自動(dòng)收集統(tǒng)計(jì)信息時(shí)該怎么辦?很簡單。只需使用以下語句來禁用調(diào)度程序作業(yè)即可:
?
BEGIN
DBMS_SCHEDULER.DISABLE('GATHER_STATS_JOB');
END;
??? 那么您為什么要這樣做呢?有很多原因 — 其中一個(gè)原因是,雖然表中大部分行發(fā)生了變化,但分布情況可能沒有改變,這在數(shù)據(jù)倉庫中很常見。在這種情況下,您不希望再次收集統(tǒng)計(jì)信息,而只是希望重用原來的統(tǒng)計(jì)信息。另一個(gè)原因可能是您正在使用分區(qū)交換功能來刷新物化視圖 (MV),并且不希望收集關(guān)于物化視圖的統(tǒng)計(jì)信息,因?yàn)殛P(guān)于被交換表的統(tǒng)計(jì)信息也會(huì)被導(dǎo)入。但是,您也可以將特定的表排除在自動(dòng)統(tǒng)計(jì)信息收集作業(yè)之外,而不需要禁止整個(gè)作業(yè)。
?
?
統(tǒng)計(jì)信息歷史
?
??? 在優(yōu)化器收集統(tǒng)計(jì)信息時(shí)可能出現(xiàn)的復(fù)雜情況之一是執(zhí)行計(jì)劃的改變 — 也就是說,原來的優(yōu)化方法在收集統(tǒng)計(jì)信息之前一直工作良好,但是在此之后,由于新收集的統(tǒng)計(jì)信息產(chǎn)生了不良計(jì)劃,導(dǎo)致查詢突然出錯(cuò)。這種問題并不少見。
?
??? 為避免這種災(zāi)難,統(tǒng)計(jì)信息的收集作業(yè)在收集新信息之前保存當(dāng)前的統(tǒng)計(jì)信息。如果出現(xiàn)問題,您總可以返回到原有的統(tǒng)計(jì)信息,或者至少可以檢查二者之間的不同之處,以便于解決問題。
?
??? 例如,假設(shè)在 5 月 31 日晚上 10:00 開始運(yùn)行表 REVENUE 上的統(tǒng)計(jì)信息收集作業(yè),而隨后查詢的性能變差。Oracle 保存了原有的統(tǒng)計(jì)信息,您可以通過執(zhí)行以下命令重新獲取這些信息:
?
begin
dbms_stats.restore_table_stats (
'ARUP',
'REVENUE',
'31-MAY-04 10.00.00.000000000 PM -04:00');
end;
?
??? 此命令恢復(fù)到 5 月 31 日晚上 10:00 為止的統(tǒng)計(jì)信息,時(shí)間信息是以 TIMESTAMP 數(shù)據(jù)類型提供。這樣您就立即還原了由新的統(tǒng)計(jì)信息收集程序所作的更改。
?
??? 您能夠恢復(fù)的時(shí)間長度是由保留參數(shù)所決定的。要查看當(dāng)前的保留參數(shù),可使用以下查詢:
?
SQL> select DBMS_STATS.GET_STATS_HISTORY_RETENTION from dual;
?
GET_STATS_HISTORY_RETENTION
---------------------------
???????????????????????? 31
?
??? 在本示例中表示可以保存相當(dāng)于 31 天的統(tǒng)計(jì)信息,但并不能予以保證。要了解統(tǒng)計(jì)信息所覆蓋到的確切時(shí)間和日期,只需使用以下查詢:
?
SQL> select DBMS_STATS.GET_STATS_HISTORY_AVAILABILITY from dual;
?
GET_STATS_HISTORY_AVAILABILITY
---------------------------------------------------------------------
17-MAY-04 03.21.33.594053000 PM -04:00
?
??? 該查詢表明可用的最陳舊統(tǒng)計(jì)信息日期為 5 月 17 日凌晨 3:21。
?
??? 您可以通過執(zhí)行內(nèi)建的函數(shù)將保留時(shí)間設(shè)為不同的值。例如,要將其設(shè)為 45 天,可使用:
execute DBMS_STATS.ALTER_STATS_HISTORY_RETENTION (45)
?
?
有保證的還原保留功能
?
??? 自動(dòng)還原保留功能是在 Oracle9i 中推出的,它極其有助于減少令人討厭的 ORA-1555 "Snapshot Too Old" 錯(cuò)誤的出現(xiàn)機(jī)率。但是這些錯(cuò)誤還是會(huì)出現(xiàn),雖然其數(shù)量已大大減少。這是為什么呢?
?
??? 要回答這個(gè)問題,您需要了解還原段是如何工作的。當(dāng) Oracle 內(nèi)部的數(shù)據(jù)發(fā)生變化時(shí),高速緩存中的塊(在 SGA 中)立即發(fā)生變化,而過去的映像被存儲(chǔ)在還原段中。當(dāng)事務(wù)提交時(shí),不再需要舊的映像,因此可以重用它們。如果還原段中的所有空間都被活動(dòng)的事務(wù)所使用,則 Oracle 將嘗試重用段中最陳舊的范圍(這一進(jìn)程稱為“折返”,如 V$ROLLSTAT 視圖中的 WRAPS 列所示)。但是,在某些情況下,特別是在長時(shí)間運(yùn)行的事務(wù)中,段將會(huì)擴(kuò)展,為活動(dòng)的事務(wù)提供空間,如 V$ROLLSTAT 中的列 EXTENDS 所示。如果查詢需要使用還原段范圍中的數(shù)據(jù)來創(chuàng)建數(shù)據(jù)的一致性視圖,但是該范圍已經(jīng)被重用,則查詢產(chǎn)生 ORA-1555 錯(cuò)誤。
?
??? 初始化參數(shù) UNDO_RETENTION_PERIOD 指定必須保留多少還原數(shù)據(jù)(以秒為單位)。通過指定時(shí)間,Oracle 確保不重用陳舊的還原范圍,即使這些范圍處于不活動(dòng)的狀態(tài),或它們?cè)谶€原保留時(shí)間內(nèi)已經(jīng)被更改,Oracle 也不會(huì)重用它們。這種方法減少了不活動(dòng)范圍以后可能被查詢所意外重用的機(jī)率,這種重用會(huì)導(dǎo)致產(chǎn)生 ORA-1555 錯(cuò)誤。
?
??? 但是,雖然 UNDO_RETENTION_PERIOD 指定了可以保留多少還原數(shù)據(jù),它并不保證得到這種結(jié)果。當(dāng)段不能擴(kuò)展范圍時(shí),最陳舊的不活動(dòng)范圍被重用,以滿足當(dāng)前事務(wù)的需要。因此,當(dāng)查詢這些范圍時(shí),某些與更改事務(wù)無關(guān)的長時(shí)運(yùn)行的查詢可能會(huì)失敗,并產(chǎn)生 ORA-1555 錯(cuò)誤。
?
??? 這個(gè)問題在 10g 中得到了解決:當(dāng)您創(chuàng)建還原表空間時(shí),您現(xiàn)在可以指定對(duì)還原保留功能的“保證”。下面是一個(gè)例子:
?
CREATE UNDO TABLESPACE UNDO_TS1
DATAFILE '/u01/oradata/proddb01/undo_ts1_01.dbf'
SIZE 1024M
RETENTION GUARANTEE;
?
??? 請(qǐng)注意最后的子句,它使還原表空間保證了對(duì)未過期還原范圍的保留。通過對(duì)現(xiàn)有還原表空間進(jìn)行 ALTER 操作,也可以使其作出保證,如下所示:
?
ALTER TABLESPACE UNDO_TS2 RETENTION GUARANTEE;
?
??? 如果您不希望對(duì)保留作出保證(Oracle9i 中的行為)該怎么辦?那么,可執(zhí)行以下操作:
?
ALTER TABLESPACE UNDO_TS2 RETENTION NOGUARANTEE;
?
??? 您可以使用以下語句來驗(yàn)證表空間是否已經(jīng)保證了還原保留功能:
?
SELECT RETENTION
FROM DBA_TABLESPACES
WHERE TABLESPACE_NAME = 'UNDO_TS1';
?
?
端到端跟蹤
?
??? 診斷性能問題的一種常見方法是啟用 sql_trace 來跟蹤數(shù)據(jù)庫調(diào)用,然后使用 tkprof 等工具來分析輸出。但是,這種方法在具有共享服務(wù)器體系結(jié)構(gòu)的數(shù)據(jù)庫中具有嚴(yán)重的局限性。在這種配置中,創(chuàng)建了若干個(gè)共享服務(wù)器進(jìn)程,為用戶的請(qǐng)求提供服務(wù)。當(dāng)用戶 BILL 連接數(shù)據(jù)庫時(shí),調(diào)度程序?qū)⑦B接傳遞到一個(gè)可用的共享服務(wù)器進(jìn)程。如果沒有可用的共享服務(wù)器進(jìn)程,則創(chuàng)建一個(gè)新進(jìn)程。如果開始跟蹤該會(huì)話,則會(huì)跟蹤由共享服務(wù)器進(jìn)程所進(jìn)行的調(diào)用。
?
??? 現(xiàn)在假設(shè) BILL 的會(huì)話變?yōu)榭臻e狀態(tài),而 LORA 的會(huì)話變?yōu)榛顒?dòng)狀態(tài)。此時(shí)最初為 BILL 提供服務(wù)的共享服務(wù)器被分配給 LORA 的會(huì)話。這樣,發(fā)出的跟蹤信息不是來自 BILL 的會(huì)話,而是來自 LORA 的會(huì)話。當(dāng) LORA 的會(huì)話變?yōu)榉腔顒?dòng)狀態(tài)時(shí),該共享服務(wù)器可以被分配給另外的活動(dòng)會(huì)話,這個(gè)會(huì)話將具有完全不同的信息。
?
??? 在 10g 中,通過使用端到端跟蹤,已經(jīng)有效地解決了這一問題。在這種情況下,跟蹤不僅根據(jù)會(huì)話進(jìn)行,還可根據(jù)客戶標(biāo)識(shí)符等可識(shí)別的名稱來進(jìn)行。一個(gè)名為 DBMS_MONITOR 的新程序包可用于此目的。
?
??? 例如,您可能希望跟蹤所有具有標(biāo)識(shí)符 account_update 的會(huì)話。為建立跟蹤,您可以執(zhí)行:
?
exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE('account_update');
?
??? 此命令開始跟蹤所有具有標(biāo)識(shí)符 account_update 的會(huì)話。當(dāng) BILL 連接數(shù)據(jù)庫時(shí),他可以使用以下語句來設(shè)置客戶標(biāo)識(shí)符:
?
exec DBMS_SESSION.SET_IDENTIFIER ('account_update')
?
??? 跟蹤對(duì)于具有標(biāo)識(shí)符 account_update 的會(huì)話起作用,因此以上的會(huì)話將會(huì)被跟蹤,并會(huì)在用戶卸出目標(biāo)目錄中產(chǎn)生一個(gè)跟蹤文件。如果另一個(gè)用戶連接數(shù)據(jù)庫并將其客戶標(biāo)識(shí)符設(shè)置為 account_update,則自動(dòng)跟蹤該會(huì)話,不需要在代碼中設(shè)置任何其他的命令。直到使用以下命令禁用跟蹤功能前,將跟蹤所有具有客戶標(biāo)識(shí)符 account_update 的會(huì)話:
?
exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE('account_update');
?
??? 作為結(jié)果的跟蹤文件可以由 tkprof 進(jìn)行分析。但是,每個(gè)會(huì)話都產(chǎn)生不同的跟蹤文件。為了正確地診斷故障,我們關(guān)心合并的跟蹤文件而不是單獨(dú)的跟蹤文件。我們?nèi)绾潍@得合并的跟蹤文件呢?
?
??? 很簡單。利用一種稱為 trcsess 的工具,您可以將那些與客戶標(biāo)識(shí)符 account_update 相關(guān)的信息提取到一個(gè)單獨(dú)的文件中,通過 tkprof 可以處理該文件。在以上的案例中,您可以轉(zhuǎn)到用戶卸出目標(biāo)目錄中并運(yùn)行:
?
trcsess output=account_update_trc.txt clientid=account_update *
?
??? 此命令創(chuàng)建一個(gè)名為 account_update_trc.txt 的文件,該文件與常規(guī)的跟蹤文件類似,但它只包含與那些具有客戶標(biāo)識(shí)符 account_update 的會(huì)話相關(guān)的信息。該文件可以使用 tkprof 進(jìn)行處理,以獲得經(jīng)過分析的輸出。
?
??? 將這種方法和前一種更困難的跟蹤信息收集方法對(duì)比此外,跟蹤是由客戶標(biāo)識(shí)符這樣的變量來啟用和禁止的,而不需要從該會(huì)話中調(diào)用 alter session set sql_trace = true。同一程序包中的另一個(gè)過程 SERV_MOD_ACT_TRACE_ENABLE 能夠在其他組合方式中啟用跟蹤功能,如用于特定服務(wù)、模塊或操作的組合,可以利用 dbms_application_info package 來進(jìn)行設(shè)置。
?
?
數(shù)據(jù)庫的使用
?
??? 您的 Oracle 銷售代表將會(huì)確認(rèn),分區(qū)功能是要額外購買的選件,而在如今這個(gè)控制成本的時(shí)代,您可能希望了解用戶是否使用該選件 — 如果使用,使用的頻率怎樣。
?
??? 不必依賴于用戶的回答,只需查詢數(shù)據(jù)庫即可。自動(dòng)工作負(fù)載信息庫(在第 6 周中有介紹)收集所有已安裝特性的使用情況信息,盡管每周只收集一次。
?
??? 兩個(gè)非常重要的視圖顯示了數(shù)據(jù)庫的使用模式。其中之一是 DBA_HIGH_WATER_MARK_STATISTICS,它顯示當(dāng)前數(shù)據(jù)庫中使用的每個(gè)特性的最大值。以下是一個(gè)示例輸出。
?
NAME???????????? HIGHWATER LAST_VALUE DESCRIPTION
--------------- ---------- ---------- ----------------------------------------------------------
USER_TABLES??????????? 401??????? 401 Number of User Tables
SEGMENT_SIZE??? 1237319680 1237319680 Size of Largest Segment (Bytes)
PART_TABLES???????????? 12????????? 0 Maximum Number of Partitions belonging to an User Table
PART_INDEXES??????????? 12????????? 0 Maximum Number of Partitions belonging to an User Index
USER_INDEXES?????????? 832??????? 832 Number of User Indexes
SESSIONS??????????????? 19???????? 17 Maximum Number of Concurrent Sessions seen in the database
DB_SIZE???????? 7940079616 7940079616 Maximum Size of the Database (Bytes)
DATAFILES??????????????? 6????????? 6 Maximum Number of Datafiles
TABLESPACES????????????? 7????????? 7 Maximum Number of Tablespaces
CPU_COUNT??????????????? 4????????? 4 Maximum Number of CPUs
QUERY_LENGTH????????? 1176?????? 1176 Maximum Query Length
?
??? 可以看到,此視圖顯示了一些有關(guān)數(shù)據(jù)庫使用情況的有價(jià)值的信息 — 如用戶創(chuàng)建了一個(gè)最多可擁有 12 個(gè)分區(qū)的表,但現(xiàn)在卻沒有使用一個(gè)分區(qū) (LAST_VALUE = 0)。這些信息在關(guān)閉狀態(tài)下也持續(xù)存在,這對(duì)于計(jì)劃操作非常有用,比如移植到不同的主機(jī)。
?
??? 但是,上述視圖仍然沒有回答我們所有的問題。它只是告訴我們?cè)?jīng)創(chuàng)建了具有 12 個(gè)分區(qū)的表,但沒有說明該特性的最后一次使用時(shí)間。另一個(gè)視圖 DBA_FEATURE_USAGE_STATISTICS 顯示了數(shù)據(jù)庫各種特性的使用情況,它可以回答這個(gè)問題。以下是該視圖分區(qū)特性的顯示情況,其中的列以縱向格式顯示。
?
DBID????????????????????????? : 4133493568
NAME????????????????????????? :Partitioning
VERSION?????????????????????? : 10.1.0.1.0
DETECTED_USAGES?????????????? : 12
TOTAL_SAMPLES???????????????? : 12
CURRENTLY_USED??????????????? :FALSE
FIRST_USAGE_DATE????????????? :16-oct-2003 13:27:10
LAST_USAGE_DATE?????????????? :16-dec-2003 21:20:58
AUX_COUNT???????????????????? :
FEATURE_INFO????????????????? :
LAST_SAMPLE_DATE????????????? :23-dec-2003 21:20:58
LAST_SAMPLE_PERIOD??????????? : 615836
SAMPLE_INTERVAL?????????????? : 604800
DESCRIPTION?????????????????? :Oracle Partitioning option is being used -
there is at least one partitioned object created.
?
??? 如本視圖所示,現(xiàn)在數(shù)據(jù)庫中沒有使用分區(qū)特性(列 CURRENTLY_USED 的值為 FALSE),最后一次使用該特性的時(shí)間是 2003 年 12 月 16 日晚上 9:20。使用信息的采樣時(shí)間為 604,800 秒或者說是 7 天,示于列 SAMPLE_INTERVAL 中。列 LAST_SAMPLE_DATE 顯示了對(duì)該使用信息的最后采樣時(shí)間,表明此信息的新舊程度。
?
??? 除了命令行接口之外,企業(yè)管理器 10g 還顯示以下信息。在 EM 中,在 Administration 標(biāo)簽處單擊 Configuration Management 下方的“Database Usage Statistics”鏈接。(參見圖 1 和圖 2。)
?
圖 1:數(shù)據(jù)庫使用情況的統(tǒng)計(jì)信息頁面
?
圖 2:數(shù)據(jù)庫使用情況的統(tǒng)計(jì)信息;下鉆特性
?
?
更容易和更安全的加密
??? 還記得程序包 DBMS_OBFUSCATION_TOOLKIT (DOTK) 嗎?它是 Oracle9i 以及更低版本的數(shù)據(jù)庫中唯一可用的加密方法。盡管該程序包對(duì)于大部分?jǐn)?shù)據(jù)庫而言已經(jīng)足夠了,但是象大多數(shù)安全產(chǎn)品一樣,它很快就無法應(yīng)付那些涉及高度敏感信息的高超的黑客攻擊。在所缺少的功能中,一個(gè)值得注意的功能是對(duì)高級(jí)加密標(biāo)準(zhǔn) (AES) 的支持,該標(biāo)準(zhǔn)是以前的數(shù)字加密標(biāo)準(zhǔn) (DES) 以及三倍 DES (DES3) 的一個(gè)功能更強(qiáng)的后繼標(biāo)準(zhǔn)。
?
??? 在 10g 中,一種更加完善的加密方法 DBMS_CRYPTO 用于處理這種問題。這個(gè)內(nèi)建的程序包提供了 DOTK 中缺少的所有功能,并且對(duì)現(xiàn)有的函數(shù)和過程進(jìn)行了增強(qiáng)。例如,DBMS_CRYPTO 可以使用新的 256 位 AES 算法進(jìn)行加密。函數(shù) ENCRYPT(也將其作為過程而超載)接受以下的幾個(gè)參數(shù):
?