XQuery 可處理**任意位置**的 XML 數據:數據庫內、HTTP URL、本地文件、Repository 資源。但 **Oracle XML DB 對數據庫內數據有極致優化** (XPath Rewrite、XMLIndex),若可控建議先入庫。
100 1200
101 1000
SELECT XMLQuery(
'for $k in 1
return {
for $i in ora:view("employees")/ROW,
$j in $emps/EMPLOYEES/EMPLOYEE
where $i/EMPLOYEE_ID = $j/EMPNO
return
{xs:string($i/EMPLOYEE_ID)}
{xs:string(fn:concat($i/FIRST_NAME, " ", $i/LAST_NAME))}
{xs:integer($j/BONUS)}
} '
PASSING XMLParse(DOCUMENT HTTPURIType('https://localhost/employees/empsbonus.xml').getCLOB()) AS "emps"
RETURNING CONTENT).GetStringVal() AS RESULT
FROM DUAL;
100 Steven King 1200
101 Neena Kochhar 1000
ora:view("employees"):將關係表暴露為 XML 視圖 (每行成 ROW 元素)HTTPURIType(...).getCLOB():HTTP 獲取外部 XML,轉為 CLOB 傳入PASSING ... AS "emps":綁定外部 XML 為 XQuery 變數 $empsxs:string(), xs:integer():顯式類型構造器確保輸出類型正確| 存儲類型 | XQuery 優化支援 | 說明 |
|---|---|---|
| 關係表 + ora:view() | ✅ 完全優化 | XPath Rewrite 轉為關係代數,利用索引/分區/並行 |
| XMLType 結構化存儲 (Object-Relational) | ✅ 完全優化 | 基於 XML Schema 註冊,列級索引、分區、統計資訊 |
| XMLType 二進制 XML (SecureFile) | ⚠️ 部分優化 | 11g+ 支援 XMLIndex、虛擬列,但無 XPath Rewrite |
| XMLType CLOB 非結構化存儲 | ❌ 無優化 | 全文檢索/函數索引為主,XQuery 需解析整個文檔 |
| 外部 HTTP/文件 XML | ❌ 無優化 | 每次查詢需下載、解析、流式處理,無統計資訊 |
鐵律:高性能 XQuery 必須建立在 **關係數據** 或 **結構化 XMLType** 之上。
-- 需先建立 PLUSTRACE 角色並授權
SET AUTOTRACE ON EXPLAIN
SELECT COUNT(*)
FROM oe.purchaseorder, XMLTable(
'for $i in /PurchaseOrder/User
where $i = "CJOHNSON"
return $i'
PASSING OBJECT_VALUE) ptab;
-- 執行計劃關鍵行:
-- | 2 | NESTED LOOPS | | 10782 | 2379K | 29 | -- 掃描 10782 行
-- | 3 | TABLE ACCESS FULL | PURCHASEORDER | 1 | 226 | 5 |
-- | 4 | COLLECTION ITERATOR | XMLSEQUENCEFROMXMLTYPE | | | |
問題:XPath /PurchaseOrder/User 迭代 XML 內部節點,**未下推到關係層**,導致全表掃描 + XML 解析。
SELECT COUNT(*)
FROM oe.purchaseorder, XMLTable(
'for $i in /PurchaseOrder
where $i/User = "CJOHNSON"
return $i/User'
PASSING OBJECT_VALUE) ptab;
-- 執行計劃關鍵行:
-- | 2 | NESTED LOOPS | | 1 | 29 | 7 | -- 僅 1 行
-- | 3 | FAST DUAL | | 1 | | 2 |
-- | 4 | TABLE ACCESS FULL | PURCHASEORDER | 1 | 29 | 5 |
-- Predicate: "PURCHASEORDER"."SYS_NC00022$"='CJOHNSON' -- 虛擬列直接過濾
優化點:迭代 **頂層 /PurchaseOrder** (對應關係表每一行),WHERE 條件下推為虛擬列 SYS_NC00022$ (User 欄位) 直接過濾,**XPath Rewrite 成功**。
XQuery 寫法微小差異 → 執行計劃天壤之別。開發階段 **必須配合 EXPLAIN PLAN/AUTOTRACE** 驗證 XPath Rewrite 是否生效,關鍵指標:
COLLECTION ITERATOR / XMLSEQUENCEFROMXMLTYPE (未重寫)SYS_NCxxxxx$ (已重寫)