2016-04-01 12 views
1

Ich habe eine sehr große XML-Datei im Maßstab von GBs zusammengeführt. Ich verwende folgenden Code mit Xpath-Abfragen zum Lesen und Verarbeiten von Daten.Abfragen sehr großer XML-Dateien

  IColumn column = output.Schema.FirstOrDefault(col => col.Type != typeof(string)); 
     if (column != null) 
     { 
      throw new ArgumentException(string.Format("Column '{0}' must be of type 'string', not '{1}'", column.Name, column.Type.Name)); 
     } 


     XmlReaderSettings settings = new XmlReaderSettings(); 
     settings.ConformanceLevel = ConformanceLevel.Auto;//.Fragment; 
     XmlReader r = XmlReader.Create(input.BaseStream, settings); 
     XmlDocument xmlDocument = new XmlDocument(); 
     xmlDocument.Load(r); 
     //xmlDocument.LoadXml("<root/>"); 

     //xmlDocument.DocumentElement.CreateNavigator().AppendChild(r); 
     //xmlDocument.Load(input.BaseStream); 

     XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDocument.NameTable); 
     if (this.namespaces != null) 
     { 
      foreach (Match nsdef in xmlns.Matches(this.namespaces)) 
      { 
       string prefix = nsdef.Groups[1].Value; 
       string uri = nsdef.Groups[3].Value; 
       nsmgr.AddNamespace(prefix, uri); 
      } 
     } 

     foreach (XmlNode xmlNode in xmlDocument.DocumentElement.SelectNodes(this.rowPath, nsmgr)) 
     { 
      foreach (IColumn col in output.Schema) 
      { 
       var explicitColumnMapping = this.columnPaths.FirstOrDefault(columnPath => columnPath.Value == col.Name); 
       XmlNode xml = xmlNode.SelectSingleNode(explicitColumnMapping.Key ?? col.Name, nsmgr); 
       output.Set(explicitColumnMapping.Value ?? col.Name, xml == null ? null : xml.InnerXml); 
      } 
      yield return output.AsReadOnly(); 
     } 

Allerdings funktioniert es nur gut für kleinere Dateien im MB-Maßstab. Es funktioniert lokal gut, aber nicht für ADLA. Ich muss auch den Namespace-Manager verwenden. Wie kann ich es skalieren, damit ich größere Dateien verarbeiten kann. Beim Übergeben eines Jobs mit einer großen Datei erhalte ich immer diesen Fehler ohne Information.

VertexFailedError

+0

Diese Dateien werden in den RAM geladen - tun Sie genug haben? –

+0

Es ist wahrscheinlich am besten, den XmlReader in diesem Fall selbst zu verwenden und das Ganze nicht in ein XmlDocument zu lesen. Es bietet schnellen, nur vorwärts gerichteten Lesezugriff. Sie können dann steuern, was Sie im Speicher haben und nicht das gesamte XML-Dokument. Es wird wahrscheinlich die Zugriffe, die Sie tun möchten, komplizierter machen, aber Sie haben zumindest eine gute Chance, sie zum Laufen zu bringen. – moreON

+0

@GerardSexton, ich habe genug RAM, um sie lokal zu verarbeiten, aber ich bin nicht sicher über ADL. Die Datei ist etwa 2,7 GB und mein lokaler RAM ist 32 GB. Gibt es eine Möglichkeit für mich, den RAM etc. nach Jobs zu durchsuchen? (PS. Sehr neu zu u-sql und ADL) –

Antwort

0

Kopieren Antwort, die ich auf diese Frage in MSDN Forum gab:

U-SQL-Extraktoren standardmäßig skaliert werden aus parallel über kleinere Teile der Eingabedateien zu arbeiten, genannt Ausdehnung. Diese Extents sind jeweils etwa 250 MB groß.

Wenn die Daten, die Sie verarbeiten, nicht in einen Extent passen, müssen Sie dem Extraktor mit einem C# -Attribut mitteilen, dass der Extraktor die Datei vollständig anzeigen muss. Sie tun das, den folgenden Teil vor Ihrer Extraktor Klasse durch Zugabe:

[SqlUserDefinedExtractor(AtomicFileProcessing = true)] 

Jetzt in Ihrem Fall, XML-Dokumente können offenbar nicht geteilt werden, da der Parser den Anfang und das Ende eines Dokument sehen muss. Dies gilt insbesondere dann, wenn Sie nur ein einziges XML-Dokument haben (Randnotiz: Die Verwendung von GBs eines einzelnen XML-Dokuments oder JSON-Dokuments ist meiner Meinung nach oft eine schlechte Idee).

Außerdem würde ich vorschlagen, dass Sie in der XML-Beispiel Extraktor suchen, die wir hier auf unserer Website zur Verfügung stellen GitHub: https://github.com/Azure/usql/tree/master/Examples/DataFormats

+0

Danke Michael. Ja, ich hatte es aus meinen Experimenten erraten. Ich folgte dem XMLReader-Beispiel von Git und erweiterte es, um Attribute und Namespaces für unseren Anwendungsfall zu unterstützen. Es hat sowohl lokal als auch mit ADL sehr gut funktioniert. Möglicherweise haben wir sie jedoch wegen des Verarbeitungsverhaltens für atomare Dateien verworfen. Millionen kleiner XML-Dateien wurden wegen der Begrenzung von 3000 Dateien zu einem großen XML-Code von GBs zusammengeführt. –

+0

Wenn Sie die XML-Dokumente verketten, indem Sie alle CR LF entfernen (oder mit der Zeichenentität in XML codieren) und sie mit CR LF trennen, können Sie einen parallelen Extraktor verwenden, vorausgesetzt, jedes XML-Dokument ist kleiner als 4 MB. –

Verwandte Themen