首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> DB2 資料庫 >> DB2 教學

DB2 pureXML 不區分大小寫搜尋最佳實踐:Unicode 排序規則讓索引生效

     編輯:DB2 教學

前言:XML 天生區分大小寫,如何優雅破解?

XML 元素/屬性值預設區分大小寫。搜尋 <city>Paris</city> 找不到 PARIS 或 paris。常見對策 fn:upper-case() 雖可行,但導致 XML 索引失效,大數據量下效能崩潰。DB2 9.5 FP1 引入 UCA500R1 區域感知 Unicode 排序規則,從資料庫層面解決大小寫不敏感,並完整保留索引效能。

問題重現:fn:upper-case() 的代價

CREATE TABLE customer (id INTEGER, xmldoc XML);
INSERT INTO customer VALUES
(1, '<Customer id="1"><city>PARIS</city></Customer>'),
(2, '<Customer id="2"><city>Tokyo</city></Customer>'),
(3, '<Customer id="3"><city>tokyo</city></Customer>'),
(4, '<Customer id="4"><city>PARIS</city></Customer>'),
(5, '<Customer id="5"><city>paris</city></Customer>'),
(6, '<Customer id="6"><city>Delhi</city></Customer>'),
(7, '<Customer id="7"><city>Paris</city></Customer>');

-- 傳統做法:轉大寫比對
SELECT id, XMLCAST(XMLQUERY('$XMLDOC/Customer/city') AS VARCHAR(15)) AS city
FROM customer
WHERE XMLEXISTS('$XMLDOC/Customer[fn:upper-case(city) = "PARIS"]');

-- 參數化查詢
WHERE XMLEXISTS('$XMLDOC/Customer[fn:upper-case(city) = fn:upper-case($c)]'
                PASSING CAST(? AS VARCHAR(15)) AS "c")

缺點:謂詞含函數 → 無法使用 /Customer/city XML 索引 → 全表掃描。

傳統查詢結果:僅回傳 Paris 大小寫完全匹配的第 7 筆

解決方案:建立不區分大小寫資料庫

關鍵指令

CREATE DATABASE testdb
USING CODESET UTF-8 TERRITORY US
COLLATE USING UCA500R1_LEN_S2;

排序規則名稱解碼

片段含義
UCA500R1Unicode Collation Algorithm 5.0.0 版本基準
LENLanguage=EN(英語規則),L=Language、EN=ISO 639-1 編碼
S2Strength Level 2:忽略大小寫,但區分重音符號

Strength Level 對照:

  • S1:cliche = Cliche = cliché(忽略大小寫+重音)
  • S2:cliche = Cliche < cliché(忽略大小寫,保留重音差異)
  • S3:cliche < Cliche < cliché(完全區分)

完整組合請查閱 DB2 Information Center「UCA 排序規則名」。

索引生效驗證

建立 XML 索引

CREATE INDEX customer_lang_idx ON test (XMLdoc)
GENERATE KEY USING XMLPATTERN '/Customer/city' AS SQL VARCHAR(15);

簡化查詢(無需 fn:upper-case)

SELECT id, XMLCAST(XMLQUERY('$XMLDOC/Customer/city') AS VARCHAR(15)) AS city
FROM customer
WHERE XMLEXISTS('$XMLDOC/Customer[city = "PARIS"]');  -- 搜尋 "Paris"、"paris" 同樣有效
不區分大小寫資料庫查詢結果:正確回傳 4 筆 Paris 資料

Explain Plan 證明索引被使用

Visual Explain 顯示 IXSCAN 走索引

Visual Explain / db2exfmt 明確顯示 IXSCAN 走 customer_lang_idx,無全表掃描。

重要限制與注意事項

  • 全庫生效:資料庫建立後,所有表、所有欄位、所有字串比較均為不區分大小寫,無法單獨指定某表/某欄位區分大小寫
  • 標記名仍區分大小寫:XPath /Customer/city vs /Customer/City 不同,只影響元素/屬性值
  • ORDER BY 行為:PARIS、paris、Paris 視為相等值,排序順序不穩定

效能影響實測

測試環境:20,000 筆 TPoX CustAcc 文件,對比一般資料庫(區分大小寫)vs 不區分大小寫資料庫。

結論:犧牲 <5% 全掃描效能,換取索引可用、查詢邏輯簡潔、應用層無需處理大小寫,極具性價比。

替代方案快速比較

查詢類型效能差異
少量/中量資料、高選擇性謂詞可忽略不計
全表掃描 + 字串比較(20,000 筆)不區分大小寫資料庫 慢 5%~8%
方案適用資料類型索引支援維護複雜度
UCA500R1_LEN_S2 排序規則XML + 關係✅ 完整支援低(一次建庫設定)
Generated Column + 一般索引關係欄位✅中(需觸發器/生成欄)
fn:upper-case() / fn:lower-case()XML❌ 索引失效低但效能差
應用層統一轉大小寫寫入XML + 關係✅高(侵入業務邏輯)

總結:最佳實踐建議

  1. 新專案若需 XML 不區分大小寫搜尋 → 建庫時直接指定 COLLATE USING UCA500R1_LEN_S2
  2. 既有資料庫無法重建 → 評估 Generated Column 或應用層正規化
  3. 務必搭配 XMLPATTERN 索引,驗證 Explain Plan 出現 IXSCAN
  4. 接受 <5% 全掃描代價,換取架構簡潔與索引效能

透過 Unicode 排序規則,DB2 pureXML 終於能像關係欄位一樣,優雅地支援大小寫不敏感搜尋——不再在應用層與索引效能之間兩難。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved