SQL Server XML性能优化(Best Practices)
1. XML數(shù)據(jù)模型
XML存儲(chǔ)與處理查詢的性能取決于數(shù)據(jù)庫的設(shè)計(jì)與XML數(shù)據(jù)的結(jié)構(gòu)與粒度。是否要使用XML數(shù)據(jù)模型,看你
是不是有半結(jié)構(gòu)化的數(shù)據(jù),需要保留文檔結(jié)構(gòu)與層次結(jié)構(gòu)的標(biāo)記語言數(shù)據(jù),或可變的結(jié)構(gòu)。
1.1 標(biāo)記 Markups
同樣的數(shù)據(jù)可以以不同的方式來標(biāo)記,視內(nèi)容(element值)與元數(shù)據(jù)信息(attribute值)。越具體的
element名越易于閱讀,且對(duì)生成有效的查詢計(jì)劃有幫助。冗長的標(biāo)記會(huì)增加存儲(chǔ)的成本。例如:
a.
<item type="book"><title>Writing Secure Code</title></item>
<item type="DVD"><title>The Godfather</title></item>
如果要查詢book,需要寫為:/item[@type = "book"]
b.
<book><title>Writing Secure Code</title></book>
<DVD><title>The Godfather</title></DVD>
如果要查詢book,只需要寫:/book ,這樣效率更高也看起來更簡單,而且減少了primary XML index(
主XML索引)的層數(shù)(少了item層)。這就是具體標(biāo)記(Specific Markups)相對(duì)一般標(biāo)記(Generic
Markups)的優(yōu)點(diǎn)。
對(duì)于被類型化的的XML(typed XML),還可以縮減到兩層:
<book title="Writing Secure Code"/>
<DVD title="The Godfather"/>
像<DVD><title>The Godfather</title></DVD>這種格式,稱為element-centric markup,查詢格式
為/DVD[title = "The Godfather"]
像<DVD title="The Godfather"/>這種格式,attribute-centric markup,查詢格式為/DVD[@title =
"The Godfather"] ,可以減少一個(gè)JOIN。
1.2 Typed 和 Untyped XML(類型化與非類型化的XML)
非類型化的XML(untyped XML,沒有以XML schema來表示)在SQL Server內(nèi)部以Unicode字符串的形式存
儲(chǔ)。對(duì)他們的操作需要數(shù)據(jù)轉(zhuǎn)換到相應(yīng)的類型。例如 (/book/price)[1] > 19.99,會(huì)有<price>轉(zhuǎn)換為
decimal的過程。大量類似的比較就會(huì)非常耗資源,這就引出了XML schema中類型信息的重要性。
類型信息在以下幾個(gè)方面起作用:
a. 插入更新的XML數(shù)據(jù)先被驗(yàn)證是否符合schema,然后以二進(jìn)制形式存儲(chǔ),方便更快地轉(zhuǎn)換
b. 類型化的值被存儲(chǔ)在XML索引中
c. 類型化的數(shù)據(jù)還可以減少范圍掃描,例如(/book/price)[1]中的序數(shù)[1]在XML schema規(guī)定了<price>
為單值時(shí)就是不必要的。
1.3 屬性
可以使用UDF(用戶自定義函數(shù))來獲得計(jì)算列(computed column)。可以在計(jì)算列上添加索引。由于計(jì)算列是預(yù)計(jì)算好的,查詢速度更快。
范例:
書籍都有ISBN號(hào),把ISBN單獨(dú)作為計(jì)算列的過程如下
a. 定義獲取ISBN號(hào)的函數(shù)
CREATE FUNCTION udf_get_book_ISBN (@xData xml) RETURNS varchar(20)
WITH SCHEMABINDING
BEGIN
?? RETURN @xData.value('(/book/@ISBN)[1]', 'varchar(20)')
END
b. 添加計(jì)算列
CREATE TABLE docs (id int PRIMARY KEY, xCol XML)
ALTER TABLE docs ADD ISBN AS dbo.udf_get_book_ISBN(xCol)
c. 添加非聚類索引
CREATE INDEX COMPUTED_IDX ON docs (ISBN)
d. 寫查詢
如果不使用ISBN列,查詢?nèi)缦?#xff1a;
SELECT xCol
FROM?? docs
WHERE? xCol.exist ('/book/@ISBN[. = "0-2016-3361-2"]') = 1
如果使用ISBN列
SELECT xCol
FROM?? docs
WHERE? ISBN = '0-2016-3361-2'
還可以建立屬性表(Property Table)
2. 批量載入XML數(shù)據(jù)
--可以使用BCP IN,BULK INSERT和OPENROWSET方法,因?yàn)楹瓦@次的case無關(guān)暫且略過。
3. XML索引
3.1 普通索引
推薦創(chuàng)建初級(jí)XML索引(primary XML index),實(shí)際上是創(chuàng)建了一個(gè)B+樹。還可以對(duì)于PATH,PROPERTY,VALUE創(chuàng)建次級(jí)XML索引(secondary XML indexes)。
a. PATH索引
適用于有類似/book[@ISBN = "0-2016-3361-2"]的路徑表達(dá)式,路徑越長越有效
b. PROPERTY索引
適用于XML中的多properties查詢
c. VALUE索引
適用于存在子軸(//操作符)和通配符(類似(/book[@* = "novel"]))的查詢
維護(hù)索引的開銷也是需要整體考慮的。
--關(guān)于XML部分更新和這次的case無關(guān)暫且略過。
--關(guān)于XML全文索引和這次的case無關(guān)暫且略過。
4. 查詢優(yōu)化
4.1 使用exist()方法來檢測(cè)是否存在
盡可能使用exist()來代替value()
比如如下的查詢:
SELECT *
FROM?? docs
WHERE??? xCol.exist('(/book/title/text())[.="Writing Secure Code"]') = 1
比
SELECT *
FROM?? docs
WHERE? xCol.value('(/book/title)[1]', 'varchar(50)') = 'Writing Secure Code'
4.2 優(yōu)化XML blobs(二進(jìn)制XML)
更多的tempDB文件可以提供更好的可擴(kuò)展性。
減少額外的XML數(shù)據(jù)類型轉(zhuǎn)換
4.3 指定Singleton Elements(單件元素)
對(duì)于類型化的XML,默認(rèn)是singleton的
非類型化的XML,需要加[1],xCol.query ('/book/title')會(huì)被自動(dòng)轉(zhuǎn)換為xCol.query ('(/book/title)[1]')。
4.4 對(duì)于非類型化的XML的text聚合
(/book/title[.="Writing Secure Code"])[1]需要聚合<title>下所有的text節(jié)點(diǎn)
如果<title> element只有一個(gè)text節(jié)點(diǎn),那么可以使用(/book/title/text())[1][. = "Writing Secure Code"]更有效。
4.5 將XQuery和XML DML表達(dá)式參數(shù)化
XQuery和XML DML不會(huì)自動(dòng)參數(shù)化,最好使用sql:column() 或sql:variable() 。
4.6 序數(shù)和預(yù)計(jì)的優(yōu)化
減少語句的分支,如/book[@ISBN = "1-8610-0157-6"]/author/first-name,最好使用/book[author/first-name = "Davis"]這樣的格式。
把序數(shù)移到路徑的最后,/book[1]/title[1]等同于 (/book/title)[1]
使用Context Node(上下文節(jié)點(diǎn))
如下的范例:
SELECT *
FROM?? docs
WHERE? xCol.exist ('/book[@subject = "security"]') =? 1
分別對(duì)/book和/book/@subject進(jìn)行了評(píng)估,并檢測(cè)了后者是否包含了值“security”
如果使用如下表達(dá):
SELECT *
FROM?? docs
WHERE? xCol.exist ('/book/@subject[. = "security"]') =? 1
只會(huì)對(duì)/book/@subject 進(jìn)行評(píng)估
動(dòng)態(tài)查詢與本次的case無關(guān)暫且略過。
具體案例等我做完這個(gè)case再詳細(xì)闡述。
參考資料:
Performance Optimizations for the XML Data Type in SQL Server 2005
http://technet.microsoft.com/en-us/library/ms345118.aspx
XML Best Practices for Microsoft SQL Server 2005
http://technet.microsoft.com/en-us/library/ms345115.aspx
轉(zhuǎn)載于:https://www.cnblogs.com/galaxyyao/archive/2009/04/23/1442417.html
總結(jié)
以上是生活随笔為你收集整理的SQL Server XML性能优化(Best Practices)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络图片爬虫程序
- 下一篇: asp.net ajax控件工具集 Au