Ich habe eine einfache Abfrage, die sehr schnell läuft (ca. 1 Sekunde), wenn ich einen Stringliteral in meiner WHERE
Klausel, wie zum Beispiel:Variable vs Stringliteral Geschwindigkeit Disparität
select *
from table
where theDate >= '6/5/2016'
jedoch diese Abfrage (das nicht wesentlich ist) läuft über 2 Minuten in:
declare @thisDate as date
set @thisDate = '6/5/2016'
select *
from table
where theDate >= @thisDate
ich mit OPTION(RECOMPILE)
versucht, so here vorgeschlagen, aber es tut nichts, um die Leistung zu verbessern. Die Spalte theDate
ist eine Datetime, diese Datenbank wurde vor kurzem aus SQL Server 2005 migriert.
Es gibt keinen Index auf meiner theDate
Spalte, und die Tabelle hat knapp über 1 Milliarde Zeilen. Es ist eine freigegebene Ressource und ich möchte nicht mit der Indizierung beginnen, ohne sicher zu sein, dass es hilft.
finde ich, dass unter Verwendung von Logik anstelle einer Variablen als String die gleiche Leistung bietet wörtlichen:
select *
from table
where theDate >= dateadd(dd, -23, getdate())
Aber, wenn ich das Datum ganze Zahl mit einem variablen integer ersetzen die Leistung wieder behindert wird.
Wie kann ich eine Variable hinzufügen und die Leistung beibehalten?
EDIT
tatsächliche Abfrage nach Anforderung enthalten:
DECLARE @days INT
Set @days = 7
select c.DEBT_KEY
, c.new_value
, c.CHANGE_DATE
from changes c with (nolock)
where c.C_CODE = 3
and c.old_value = 4
and c.CHANGE_DATE >= dateadd(dd, [email protected], getdate())
Nein verbindet.
Abfragepläne
Mit Variable (xml explain plan):
Mit Stringliteral (xml explain plan):
So kann ich der Unterschied zu sehen ist tha t Die Variable ruft einen Clustered-Index-Scan (gruppiert) auf, während das String-Literal ein Key-Lookup (Clustered) aufruft ... Ich werde auf Google verweisen müssen, weil ich nicht wirklich etwas über die Performance-Pro/Contra-Werte weiß.
EDIT EDIT
Das funktionierte (xml explain plan):
DECLARE @days INT
Set @days = 7
select c.DEBT_KEY
, c.new_value
, c.CHANGE_DATE
from changes c with (nolock)
where c.CHANGE_CODE = 3
and c.old_value = 4
and c.CHANGE_DATE >= dateadd(dd, [email protected], getdate())
OPTION(OPTIMIZE FOR (@days = 7))
... Ich weiß nicht, warum. Außerdem mag ich die Lösung nicht, da sie meinen Zweck der Verwendung einer Variablen negiert, die darin besteht, alle Variablen an die Spitze des Procs zu setzen, um die Notwendigkeit zu reduzieren, im Code während der unvermeidlichen Wartung herumzustochern.
über 1 Milliarde Zeilen und kein Index - wow! Diese Menge nach einem Literal zu suchen, sollte auch ziemlich lange dauern ... Ich würde annehmen, dass es irgendwelche gecachten Ergebnisse gab ... Hast du die Ausführungspläne verglichen? * Ich möchte nicht mit der Indexierung beginnen, ohne sicher zu sein, dass es hilft * Nun kann ich Ihnen versichern, dass ein Index helfen wird :-) – Shnugo
Nun, es gibt einen Index, aber nicht auf 'theDate', ich könnte es gewesen sein Klarer dazu: P –
Bei so vielen Zeilen sollten Sie Indizes für alle Spalten verwenden, die Sie bei Sortier-, Filter- oder Join-Operationen verwenden möchten ... Ein Index ist - einfach gesprochen - eine sortierte Liste der Werte dieser Spalte. Um einen bestimmten Wert in dieser Liste zu finden, ist ein extrem schneller Prozess (teile die Hälfte, schau, ob größer oder kleiner, ah, es ist größer! Teile die obere Hälfte und so weiter ...) Sobald gefunden, sitzen alle Werte zusammen Block. Stellen Sie sich nun einen unsortierten Haufen vor. Ihre Abfrage muss die gesamte Tabelle Zeile für Zeile durchsuchen. – Shnugo