Ich habe eine Tabelle mit vielen großen XML-Dokumenten.
Wenn ich xpath-Ausdrücke ausführe, um Daten aus diesen Dokumenten auszuwählen, tritt ein besonderes Leistungsproblem auf.
Meine Anfrage ist
SELECT
p.n.value('.', 'int') AS PurchaseOrderID
,x.ProductID
FROM XmlLoadData x
CROSS APPLY x.PayLoad.nodes('declare namespace NS="http://schemas.datacontract.org/2004/07/XmlDbPerfTest";
/NS:ProductAndRelated[1]/NS:Product[1]/NS:PurchaseOrderDetails[1]/NS:PurchaseOrderDetail/NS:PurchaseOrderID[1]') p(n)
Die Abfrage dauert 2 Minuten und 8 Sekunden.
Wenn ich die [1]
Teile der einzelnen Vorkommensknoten wie folgt entferne :
SELECT
p.n.value('.', 'int') AS PurchaseOrderID
,x.ProductID
FROM XmlLoadData x
CROSS APPLY x.PayLoad.nodes('declare namespace NS="http://schemas.datacontract.org/2004/07/XmlDbPerfTest";
/NS:ProductAndRelated/NS:Product/NS:PurchaseOrderDetails/NS:PurchaseOrderDetail/NS:PurchaseOrderID') p(n)
Die Ausführungszeit sinkt auf nur 18 Sekunden.
Da die [1]
-knoten in jedem übergeordneten Knoten in den Dokumenten nur einmal vorkommen, sind die Ergebnisse bis auf die Reihenfolge gleich.
Der tatsächliche Ausführungsplan für die erste (langsame) Abfrage lautet
und die zweite (schnellere) Abfrage ist
Abfrage 1 Vollbild Abfrage 2 Vollbild .
Soweit ich sehen kann, führt die Abfrage mit [1]
dieselbe Ausführung aus wie die Abfrage ohne, jedoch mit einigen zusätzlichen Berechnungsschritten, um das erste Element zu finden.
Meine Frage ist, warum die zweite Abfrage schneller ist.
Ich hätte erwartet, dass die Ausführung der Abfrage mit [1]
vorzeitig unterbrochen wird , wenn eine Übereinstimmung gefunden wird, und somit die Ausführungszeit anstelle des Gegenteils verkürzt.
Gibt es Gründe, warum die Ausführung nicht vorzeitig unterbrochen wird [1]
und somit die Ausführungszeit verkürzt wird?
Das ist mein Tisch
CREATE TABLE [dbo].[XmlLoadData](
[ProductID] [int] NOT NULL,
[PayLoad] [xml] NOT NULL,
[Size] AS (len(CONVERT([nvarchar](max),[PayLoad],0))),
CONSTRAINT [PK_XmlLoadData] PRIMARY KEY CLUSTERED
(
[ProductID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Bearbeiten:
Leistungszahlen aus SQL Profiler:
Abfrage 1:
CPU Reads Writes Duration
126251 1224892 0 129797
Abfrage 2:
CPU Reads Writes Duration
50124 612499 0 16307
quelle
Antworten:
Die zweite Abfrage verwendet Parallelität. Das heißt, es war teuer genug für den Optimierer, die Augen vor dem zusätzlichen Aufwand zu verschließen.
Ich denke, die zweite Abfrage weist den Optimierer an, "alles zu sichern", was mit einem parallelen Scan durchgeführt wird. SQL Server möchte auf Anfrage auf diese Weise "alles sichern".
Während die erste Abfrage nach "analysieren und dann etwas geben" fragt. Der Optimierer kann ohnehin nicht wissen, dass es nur einen Knoten gibt, daher ist der Ausführungsplan, den er letztendlich auswählt, sehr unterschiedlich.
Ich würde sagen, es ähnelt einer Situation, in der ein Tabellenscan billiger ist als viele Indexsuchen.
quelle
Sehen Sie sich die Leistungsoptimierungen für den XML-Datentyp in SQL Server 2005 und den Abschnitt "Verschieben von Ordnungszahlen an das Ende von Pfaden" an.
quelle
Das Abfragen von XML ist ein Biest. Das Hinzufügen von XML-Indizes zu Ihrer Tabelle beschleunigt die Abfragen erheblich.
quelle