再加上若使用了 XPath 的函式或一些判斷式後, 整個 XmlDocument 的查詢效能會變慢. (參考以下的例子)
本文章所使用的 XML 內容 (ad.xml : 紀錄一些廣告圖與連結):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <? xml version = "1.0" encoding = "utf-8" ?> < ads > < item > < title >我的E政府</ title > < weight >10</ weight > </ item > < item > < title >PChome Online 網路家庭</ title > < weight >9</ weight > </ item > < item > < title >Yahoo!奇摩</ title > < weight >9</ weight > </ item > < item > < title >巴哈姆特電玩資訊站</ title > < weight >9</ weight > </ item > </ ads > |
(程式部分用迴圈跑 10000 次, 來區分兩種做法的效能)
- 使用 XPath 做篩選: 12345678910111213
XmlDocument doc =
new
XmlDocument();
doc.Load(
"ad.xml"
);
DateTime dtStart = DateTime.Now;
for
(
int
i = 0; i < 10000; i++)
{
XmlNodeList nodes = doc.SelectNodes(
"//item[weight='9']"
);
foreach
(XmlNode node
in
nodes)
{
string
s = node.OuterXml;
}
}
Console.WriteLine((
"{0} (毫秒)"
+ DateTime.Now - dtStart).Milliseconds);
//輸出了: 337 (毫秒)
- 在程式中判斷: 12345678910111213141516
XmlDocument doc =
new
XmlDocument();
doc.Load(
"ad.xml"
);
DateTime dtStart = DateTime.Now;
for
(
int
i = 0; i < 10000; i++)
{
XmlNodeList nodes = doc.SelectNodes(
"//item"
);
foreach
(XmlNode node
in
nodes)
{
if
(node[
"weight"
].InnerText ==
"9"
)
{
string
s = node.OuterXml;
}
}
}
Console.WriteLine((
"{0} (毫秒)"
+ DateTime.Now - dtStart).Milliseconds);
//輸出了: 250 (毫秒)
儘管效能上有差異, 還是可以視情況選擇 XPath 使用的方式. 例如僅單純地使用樹狀結構查詢所需的節點, 並避免在 XPath 中使用一些函式去做文字或屬性值的判斷.
自從 .Net 出了 Linq 後, 個人感覺對 XML 的查詢更有幫助了. (效能部分因為是端看怎麼查詢, 較為主觀, 這邊就不比較效能)
以上述的例子來看, 我們可以用 Linq 的語法進行查詢: (僅供參考: 效能大約介於上述兩個做法, 300毫秒上下)
1 2 3 4 5 6 7 8 9 | XmlDocument doc = new XmlDocument(); doc.Load( "ad.xml" ); var query = from n in doc.SelectNodes( "//item" ).Cast<XmlNode>() where int .Parse(n[ "weight" ].InnerText) == 9 select n; foreach (XmlNode node in query) { string s = node.OuterXml; } |
假設本文所使用的 ad.xml 檔案是一個網站用來呈現廣告的資料來源, 在前台會顯示的廣告圖共有三個, 其中權重 (<weight>) 為10的是一定要呈現的廣告, 若權重相同, 則以亂數決定.
基於少述的條件, 可以大概知道查詢上除了權重 (<weight>)外, 還要加上一個隨機的查詢條件, 以造成圖片有隨時更換的效果.
如果用過去的查詢方式, 大概會是如下的步驟:
- 先查出權重最高的並以亂數排序: 將權重為10的 <item> 再搭配上一個亂數進行排序, 然後將前三名取出.
- 如果權重為10的項目未超過三個, 需再從權重小於10的項目中再選出, 選的過程還是要加入隨機值做排序.
- 一直重覆第2步, 直到滿足廣告所需出現的數量 (ex: 三個) .
現在, 換用 Linq 做, 程式碼大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //廣告最多3則 int intAdCount = 3; //產生亂數的物件 Random rnd = new System.Random(( int )DateTime.Now.Ticks); XmlDocument doc = new XmlDocument(); doc.Load( "ad.xml" ); var query = (from n in doc.DocumentElement.SelectNodes( ".//item" ).Cast<XmlNode>() orderby Convert.ToInt32(n[ "weight" ].InnerText) descending, rnd.Next(0, 10) descending select n).Take(intAdCount); foreach (XmlNode node in query) { string strTitle = node[ "title" ].InnerText; string strImage = node[ "image" ].InnerText; string strUrl = node[ "url" ].InnerText; } |
由於在 Linq 中可以用到 .Net Framework的函式庫, 所以像是日期或字串的判斷, 也就顯得更為彈性.
以上供參考, 例子舉得不好請見諒.
PS. 上述的例子, 將第7行後的程式以迴圈方式連續執行10000次, 大約花200毫秒, 效能上並不會因為用了 Linq 而不好.
沒有留言:
張貼留言