簡體   English   中英

極慢的xpath搜索(ruby / nokogiri)

[英]Extremely slow xpath search (ruby/nokogiri)

我正在使用Nokogiri / Ruby來解析非常大的XML文檔(約30萬行)。 處理每條記錄大約需要五分鍾,我確定下面代碼中的最后一行占用了該時間的99%。 關於如何加快搜索的任何建議? 可能是系統內存出現問題(或內存不足)嗎?

doc = Nokogiri::XML(File.read(ARGV[0]))
orders = doc.xpath("//order")

order = orders.xpath("//order[account_number=#{sap_account}]")

快速修復

使用從root而不是//的完整路徑嘗試一個XPath。

例:

order = doc.at("/full/path/to/order[account_number=#{sap_account}]")

//掃描整個文檔,因此這是在嘗試提高性能時要擺脫的第一件事。

如果您確實想加快速度,請使用SAX或Reader接口。

真實速度:閱讀器界面

Reader接口(以及SAX)將更快,因為它不必將整個文檔解析為DOM。 它只會一次線性地在文檔中一次通過一個節點。 這使您在犧牲便利性的前提下獲得了速度(無需查詢和回溯)。 相反,您必須測試每個節點的條件。

這是一個使用Reader接口(比SAX簡單一點)的示例。 說您有以下文件:

<orders>
  <order account_number="1">
    <item>Foo</item>
  </order>
  <order account_number="2">
    <item>Bar</item>
  </order>
  <order account_number="3">
    <item>Baz</item>
  </order>
</orders>

假設您account_number2的順序拉出<item> 這是代碼:

require 'nokogiri'
filename = ARGV[0]
sap_account = "2"

File.open(filename) do |file|
  Nokogiri::XML::Reader.from_io(file).each do |node|
    if node.name == 'order' and node.attribute('account_number') == sap_account
      puts node.inner_xml
    end
  end
end

輸出:

<item>Bar</item>

雖然將一個或多個節點的搜索分為多個步驟通常很有用,但實際上看起來您可以一次完成此操作:

doc = Nokogiri::XML(File.read(ARGV[0]))
order = doc.xpath("//order[account_number=#{sap_account}]")

如果該節點只能出現一次,請使用:

order = doc.at("//order[account_number=#{sap_account}]")

區別在於xpath返回一個NodeSet,它是Node的集合。 NodeSet支持許多相同的方法,但是它們會導致細微的差異,因為它們被應用於類似數組的結構而不是單個節點。 at返回第一個匹配的節點,因此您對返回的Node進行的任何進一步處理將僅應用於該節點,而不會進行其他任何處理。

xpath是特定於XPath的search版本,具有與CSS選擇器匹配的css方法。 search接受CSS和XPath選擇器,並確定要動態使用的選擇器。 同樣, at具有at_cssat_xpath CSS和XPath推論。 當我將XPath誤認為CSS導致Nokogiri瘋狂時,我傾向於使用searchat並且僅使用CSS和XPath變體。

Nokogiri應該非常快速地搜索並找到//order[account_number=#{sap_account}] ,即使它有足夠的內存可以使用,即使在300K行中也是如此。

如果不是,那么請認真考慮將XML導入數據庫並在其中進行搜索。 XML並不是真的要用作數據存儲,因此對XML文件進行處理可能會違反流程,使您的生活更加艱難。 創建架構並將其導入具有索引字段的數據庫中,可以大大加快處理速度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM