我們的文章會在微信公眾號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,便於排查問題。


第三章:最酷的功能——把系統命令變成一張可查詢的表

這是外部表最強大、最有趣的功能之一。它允許你在讀取數據之前,先執行一個操作系統命令或腳本,然後將命令的輸出結果作為表數據來查詢!

這能用來做什麼呢?

  1. 動態監控系統:直接在數據庫裏查“磁盤還剩多少空間?”“當前運行了哪些進程?”
  2. 文件搜索與過濾:在加載數據前,先讓系統命令幫你找到需要的文件,或者對文件內容進行初步處理。
  3. 處理壓縮文件:直接查詢一個 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查詢搞定!這個查詢會:

  1. df 表獲取磁盤空間。
  2. DBA_DATA_FILES 系統視圖獲取數據庫文件大小。
  3. 通過巧妙的連接和計算,直接給出“OK”或“空間不足”的最終狀態。

總結

通過這篇文章,我們看到外部表遠不止是加載固定數據文件的工具。通過 ALTER TABLE ... LOCATION 它可以靈活切換源文件;通過 PREPROCESSOR

------------------作者介紹-----------------------

姓名:黃廷忠

個人博客: (http://www.htz.pw)

CSDN地址: (https://blog.csdn.net/wwwhtzpw)

博客園地址: (https://www.cnblogs.com/www-htz-pw)