我們的文章會在微信公眾號IT民工的龍馬人生和博客網站( www.htz.pw )同步更新 ,歡迎關注收藏,也歡迎大家轉載,但是請在文章開始地方標註文章出處,謝謝! 由於博客中有大量代碼,通過頁面瀏覽效果更佳。
本文為個人學習《Expert Oracle Database Architecture Techniques and Solutions for High Performance and Productivity(第四版本》一書過程中的筆記與理解分享,僅用於學習與交流,部分內容參考原書觀點並結合>實際經驗進行整理。若涉及版權問題,請聯繫刪除或溝通處理。也請大家支持購買原版書籍。
“外部表”的進階使用,它主要解決了三個核心問題:如何切換文件、多用户怎麼辦,以及一個非常酷的玩法——把系統命令變成表。
第一章:如何用一張外部表,加載不同的文件?
場景: 想象一下,你有一個每週都要做的工作:把一個新的數據文件(比如 file1.dat,下週是 file2.dat)加載到數據庫裏。如果每次都要為的新文件重新創建一個外部表,那就太麻煩了。
解決方案:超級簡單! 就像給手錶調時間一樣,你只需要一條簡單的 SQL 命令,就能改變外部表指向的文件:
ALTER TABLE SYS_SQLLDR_X_EXT_DEPT LOCATION('file2.dat');
執行完這條命令後,下一次任何人查詢這張外部表,它讀取的就是全新的 file2.dat 文件了。這就好比給一個快遞收貨點換了新的門牌號,以後所有寄到新地址的包裹都會送到這裏。
第二章:多用户同時使用,會亂套嗎?
潛在問題: 既然表的位置可以改,那麼如果張三想把表指向 文件A,同時李四又想把它指向 文件B,會不會打架?答案是:會的。
外部表在某個時刻只能指向一個固定的位置(一個或多個文件)。如果兩個人幾乎同時去修改它,那麼最終這張表只會聽最後一個人的,導致兩個人可能都在處理同一個文件,造成混亂。
但是,別擔心!這在現實中很少發生。
因為外部表通常不被當作日常查詢的普通表來用,它更像是DBA(數據庫管理員)或開發人員手中的一個“數據加載工具”。一個聰明的DBA不會笨拙地一個一個文件去處理,而是會這樣做:
ALTER TABLE SYS_SQLLDR_X_EXT_DEPT LOCATION('file1.dat', 'file2.dat');
看,一次性告訴外部表所有需要加載的文件,讓數據庫自己去高效地處理它們(數據庫本身就支持並行處理,速度飛快)。所以,那種“多用户爭搶”的場景在實際規範的運維中很難出現。
一個小貼士:處理日誌文件 當很多人同時使用外部表時,產生的錯誤日誌和運行日誌可能會混在一起。為了解決這個問題,你可以在文件名中使用特殊變量:
%p:代表進程ID,每個會話都不同。%a:代表並行處理的服務器編號。
這樣,每個會話或處理進程都會生成自己獨立的日誌文件,比如 demo1_7108.bad,便於排查問題。
第三章:最酷的功能——把系統命令變成一張可查詢的表
這是外部表最強大、最有趣的功能之一。它允許你在讀取數據之前,先執行一個操作系統命令或腳本,然後將命令的輸出結果作為表數據來查詢!
這能用來做什麼呢?
- 動態監控系統:直接在數據庫裏查“磁盤還剩多少空間?”“當前運行了哪些進程?”
- 文件搜索與過濾:在加載數據前,先讓系統命令幫你找到需要的文件,或者對文件內容進行初步處理。
- 處理壓縮文件:直接查詢一個
gz壓縮包裏的內容,數據庫會自動先解壓再讀取。
實戰演練:在數據庫裏監控磁盤空間
背景:公司的數據庫文件都放在 /u01/oradata 目錄下,它們可以自動變大。為了保證安全,需要確保這個磁盤的剩餘空間至少是所有數據庫文件總大小的20%。
傳統方法:寫一個複雜的腳本,先通過 df 命令查看空間,再計算數據庫文件大小,最後對比分析。
高級玩法:創建一個外部表,讓它直接執行 df 命令!
步驟1:準備命令腳本 我們創建一個安全的Shell腳本 /orahome/oracle/bin/run_df.bsh,內容就是執行 df 命令:
#!/bin/bash
/bin/df -Pl # 使用完整的命令路徑,避免安全風險
步驟2:創建“磁盤信息表” 我們創建一張特殊的外部表,它的數據源不是文件,而是上面那個腳本的執行結果。
CREATE TABLE df (
fsname VARCHAR2(100), -- 文件系統名
blocks NUMBER, -- 總塊數
used NUMBER, -- 已用
avail NUMBER, -- 可用
capacity VARCHAR2(10), -- 使用率
mount VARCHAR2(100) -- 掛載點
)
ORGANIZATION EXTERNAL (
TYPE ORACLE_LOADER
DEFAULT DIRECTORY exec_dir
ACCESS PARAMETERS (
RECORDS DELIMITED BY NEWLINE
PREPROCESSOR exec_dir:'run_df.bsh' -- 關鍵!指定要運行的腳本
SKIP 1 -- 跳過 `df` 命令輸出的第一行標題
FIELDS TERMINATED BY WHITESPACE -- 用空格分割每一列
)
LOCATION ('run_df.bsh') -- 這裏隨便寫個文件名就行,因為數據來自預處理腳本
);
大功告成! 現在,你可以像查詢普通表一樣,查看磁盤空間了:
SELECT * FROM df;
更進一步:解決業務問題 有了這張“磁盤信息表”,之前那個“檢查空間是否大於20%”的複雜問題,就可以用一個SQL查詢搞定!這個查詢會:
- 從
df表獲取磁盤空間。 - 從
DBA_DATA_FILES系統視圖獲取數據庫文件大小。 - 通過巧妙的連接和計算,直接給出“OK”或“空間不足”的最終狀態。
總結
通過這篇文章,我們看到外部表遠不止是加載固定數據文件的工具。通過 ALTER TABLE ... LOCATION 它可以靈活切換源文件;通過 PREPROCESSOR
------------------作者介紹-----------------------
姓名:黃廷忠
個人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客園地址: (https://www.cnblogs.com/www-htz-pw)