2012-04-08 13 views
1

Wir verwenden eine XML-Spalte neben dem traditionellen Säulen in ein paar Tabellen in unserer SQL Server 2008 R2-Datenbank mit der Struktur wie folgt:SQL XML - existieren: Gibt es einen besseren Weg?

<bridging> 
    <project id="43" source="true" /> 
    <project id="48" source="false" /> 
    <project id="99" source="false" /> 
    <project id="123" source="false" /> 
</bridging> 

Dann wählen wir Daten aus diesen Tabellen mit einem .exist Verwendung von gespeicherten Procs XPath-Abfrage in der WHERE-Klausel wie folgt:

SELECT 
    e.ID, 
    e.ProjectsBridge, 
    e.Quantity, 
    e.Rate, 
    e.UOMID, 
    u.Name as UOM 
FROM  
    tblEstimator e LEFT OUTER JOIN 
    tblUnitOfMeasure u ON u.ID = e.UOMID 
WHERE 
    (e.ProjectsBridge.exist('//bridging/project/@id[. = sql:variable("@ProjectID")]') = 1 OR 
    @ProjectID IS NULL) 

diese sehr gut auf einem kleineren Datenmenge funktioniert, aber je größer die Datenmenge ist, desto langsamer das bekommt - das obige Beispiel auf einem Datensatz von einem weit über 2 Minuten in Betrieb Millionen-ungerade Datensätze.

Die Frage ist also, ob es eine bessere, schnellere Möglichkeit gibt, diese Abfrage durchzuführen?

Würde ein XML-Schema auf die Spalte einen signifikanten Unterschied machen?

+0

Ich weiß nicht, wie groß die Xml-Dokumente Sie haben in der Datenbank sind aber von XPath Sicht Nachfahr-oder-Selbst-Achse (d. h. "//") ist eine der kostenintensivsten Operationen. Versuchen Sie, Ihren XPath in '/ bridging/project [@id = sql: variable ("@ ProjectID")] zu ändern und sehen Sie, ob sich die Geschwindigkeit etwas erhöht. Ich weiß nicht, ob das Verwenden des Schemas die Dinge beschleunigen kann, aber mein Bauchgefühl ist, dass es nicht geht. Ich vermute, dass es nur verhindert, dass Dokumente in die Datenbank eingefügt werden, die nicht gemäß dem Schema gültig sind. – Pawel

+0

Ich habe versucht, ein Schema anzuwenden, und das macht kaum einen Unterschied, und das Ändern des XPath wie oben gewinnt mich 1 Sekunde auf 138, also kein Gewinn wirklich zu sprechen. Danke für die Antwort! – ReinhardtB

Antwort

1

Ein paar Dinge, die Sie ausprobieren können:

auch mehr kann ein CROSS APPLY sein effizient in Ihrem Kontext:

SELECT e.ID 
FROM tblEstimator e 
CROSS APPLY e.ProjectsBridge.nodes('/bridging/project') AS T(c) 
WHERE T.c.value('@id', 'INT') = @ProjectId 
+0

Danke Nip für die umfassende Antwort - ich gehe durch diese eins nach dem anderen. Bis jetzt, spart mir das CROSS APPLY (das ich zu einem OUTER APPLY wechseln musste, weil es kein straighter Join ist) vier Sekunden auf 138 - keine große Ersparnis. Ich werde über die anderen Optionen berichten, sobald ich sie ausprobiert habe. Danke noch einmal! – ReinhardtB

+0

Durch das Hinzufügen eines primären XML-Index wird die Abfrageausführung auf 47 Sekunden reduziert - eine Einsparung von 63% !!! Übrigens läuft das '/ bridging/project [@id' XPath hier doppelt so lange wie '// bridging/project/@ id [.'. – ReinhardtB

+0

Das Hinzufügen von sekundären XML-Indizes erhöht die Ausführungszeit bei '// bridging/project ...' auf 127 Sekunden, bei '/ bridging/project ...' auf 92 Sekunden. Auch nicht nützlich. So weit sind es primäre XML-Indizes FTW! Nur berechnete Spalten übrig zu versuchen ... – ReinhardtB

Verwandte Themen