it-swarm.com.de

Vergleichen von zwei Abfragen in SQL Server 2012

Ich vergleiche zwei Abfragen in SQL Server 2012. Das Ziel besteht darin, alle relevanten Informationen zu verwenden, die vom Abfrageoptimierer verfügbar sind, wenn die beste Abfrage ausgewählt wird. Beide Abfragen führen zu denselben Ergebnissen. die maximale Bestell-ID für alle Kunden.

Das Löschen des Pufferpools erfolgte vor dem Ausführen jeder Abfrage mit FREEPROCCACHE und DROPCLEANBUFFERS

Welche Abfrage ist anhand der folgenden Informationen die bessere Wahl?

-- Query 1 - return the maximum order id for a customer
SELECT orderid, custid
FROM Sales.Orders AS O1
WHERE orderid = (SELECT MAX(O2.orderid)
                 FROM Sales.Orders AS O2
                 WHERE O2.custid = O1.custid);


-- Query 2 - return the maximum order id for a customer
SELECT MAX(orderid), custid
FROM Sales.Orders AS O1
group by custid
order by custid

STATISTIKZEIT

Abfrage 1 STATISTIKZEIT: CPU-Zeit = 0 ms, verstrichene Zeit = 24 ms

Abfrage 2 STATISTIKZEIT: CPU-Zeit = 0 ms, verstrichene Zeit = 23 ms

STATISTICS IO

Abfrage 1 STATISTIK IO: Tabelle 'Bestellungen'. Scananzahl 1, logische Lesevorgänge 5, physische Lesevorgänge 2, Vorlesevorgänge 0, Lob-Lesevorgänge 0, Lob-Lesevorgänge 0, Lobvorlesevorgänge 0.

Abfrage 2 STATISTIK IO: Tabelle 'Bestellungen'. Scananzahl 1, logische Lesevorgänge 4, physische Lesevorgänge 1, Vorlesevorgänge 8, Lob-Lesevorgänge 0, Lob-Lesevorgänge 0, Lobvorlesevorgänge 0.

Ausführungspläne

enter image description here

SELECT-Eigenschaften Abfrage 1

enter image description here

SELECT-Eigenschaften Abfrage 2

enter image description here

Schlussfolgerungen :

Abfrage 1

  1. Chargenkosten 48%
  2. Logische Lesevorgänge 5
  3. Physische Lesevorgänge 2
  4. Vorauslesen Liest: 0
  5. CPU-Zeit: 0 ms
  6. Verstrichene Zeit 24ms
  7. Geschätzte Teilbaumkosten: 0,0050276
  8. CompileCPU: 2
  9. CompileMemory: 384
  10. CompileTime: 2

Abfrage 2

  1. Chargenkosten 52%
  2. Logische Lesevorgänge 4
  3. Physikalische Lesungen 1
  4. Vorlesen Liest: 8
  5. CPU-Zeit 0
  6. Verstrichene Zeit 23ms
  7. Geschätzte Teilbaumkosten: 0,0054782
  8. CompileCPU: 0
  9. CompileMemory: 192
  10. CompileTime: 0

Persönlich, obwohl Abfrage 2 gemäß dem grafischen Plan höhere Stapelkosten hat, denke ich, dass es effizienter ist als Abfrage 1. Dies, da Abfrage 2 weniger logische Lesevorgänge erfordert, eine etwas geringere verstrichene Zeit hat, sind die Werte für Compilecpu, Compilememory und Compiletime niedriger. Read-Ahead-Lesevorgänge sind 8 für Abfrage 2 und 0 für Abfrage 1.

pdate 12:

Clustered Index Definition

ALTER TABLE [Sales].[Orders] ADD  CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED 
(
    [orderid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

Nicht gruppierter Index idx_nc_custid

CREATE NONCLUSTERED INDEX [idx_nc_custid] ON [Sales].[Orders]
(
    [custid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
14
Craig Efrein

Ich mag Ihren Ansatz, die Optionen und Pläne für die Optimierung und Überprüfung von Abfragen sorgfältig zu prüfen. Ich wünschte, mehr Entwickler hätten dies getan. Eine Vorsicht wäre - testen Sie immer mit vielen Zeilen und betrachten Sie die logischen Lesevorgänge. Dies ist eine kleinere Tabelle. Versuchen Sie, eine Beispiellast zu generieren, und führen Sie die Abfrage erneut aus. Ein kleines Problem: In Ihrer oberen Abfrage fragen Sie nicht nach einer Bestellung von, in Ihrer unteren Abfrage sind Sie es. Sie sollten sie jeweils mit der Bestellung vergleichen und gegenüberstellen.

Ich habe gerade schnell eine SalesOrders-Tabelle mit 200.000 Kundenaufträgen erstellt - immer noch nicht riesig. Und führte die Abfragen mit jeweils ORDER BY aus. Ich habe auch ein bisschen mit Indizes gespielt.

Ohne Clustered-Index für OrderID, nur ohne Clustered-Index für CustID Die zweite Abfrage hat eine Outperformance erzielt. Vor allem bei der Bestellung von jeweils enthalten. Bei der ersten Abfrage wurden doppelt so viele Lesevorgänge durchgeführt wie bei der zweiten Abfrage, und die Kostenprozentsätze zwischen den Abfragen betrugen 67%/33%.

Mit einem Clustered-Index für OrderID und einem Nicht-Clustered-Index nur für CustID Sie wurden mit einer ähnlichen Geschwindigkeit und genau der gleichen Anzahl von Lesevorgängen ausgeführt.

Daher würde ich vorschlagen, dass Sie die Anzahl der Zeilen erhöhen und weitere Tests durchführen. Aber meine abschließende Analyse Ihrer Fragen -

Möglicherweise verhalten sie sich ähnlicher als Sie denken, wenn Sie die Zeilen vergrößern. Denken Sie also an diese Einschränkung und testen Sie sie auf diese Weise.

Wenn alles, was Sie jemals zurückgeben möchten, die maximale Bestell-ID für jeden Kunden ist und Sie feststellen möchten, dass die Bestell-ID die größte Bestell-ID ist, ist die zweite Abfrage von diesen beiden der beste Weg, um aus meiner Sicht herauszukommen - es ist ein bisschen Einfacher und zwar etwas teurer, basierend auf den Kosten des Teilbaums, ist es jedoch schneller und einfacher, Aussagen zu entschlüsseln. Wenn Sie beabsichtigen, eines Tages weitere Spalten zu Ihrer Ergebnismenge hinzuzufügen? Dann können Sie dies mit der ersten Abfrage tun.

Aktualisiert : Einer Ihrer Kommentare unter Ihrer Frage war:

Bitte beachten Sie, dass das Finden der besten Abfrage in dieser Frage ein Mittel ist, um die zum Vergleichen verwendeten Techniken zu verfeinern.

Der beste Weg, dies zu tun - Test mit mehr Daten - stellt jedoch immer sicher, dass Sie Daten haben, die mit der Produktion und der erwarteten zukünftigen Produktion übereinstimmen. Abfragepläne beginnen mit der Suche nach Daten, wenn Sie den Tabellen mehr Zeilen zuweisen und versuchen, die Verteilung so zu halten, wie Sie es in der Produktion erwarten würden. Und achten Sie auf Dinge wie Order By oder nicht, hier denke ich nicht, dass es am Ende einen schrecklichen Unterschied macht, aber es lohnt sich immer noch, sich damit zu beschäftigen.

Ihr Ansatz, diesen Detaillierungsgrad und diese Daten zu vergleichen, ist gut. Teilbaumkosten sind meistens willkürlich und bedeutungslos, aber es lohnt sich immer noch, zumindest einen Vergleich zwischen Bearbeitungen/Änderungen oder sogar zwischen Abfragen anzustellen. Ein Blick auf die Zeitstatistik und die IO sind wichtig) ist ebenso wichtig wie der Blick auf den Plan für alles, was sich für die Größe der Daten, mit denen Sie arbeiten, und für das, was Sie versuchen, unangebracht anfühlt tun.

10
Mike Walsh