Wie ypercube kommentierte
Nein, wenn die Abfrage das ist, was Sie zeigen, ist er völlig falsch. Es ist ziemlich sargable wie es ist.
Sie können dies überprüfen, indem Sie:
- Erstellen einer einfachen Testtabelle mit einer Spalte [Datum].
- Fügen Sie eine große Anzahl von Zeilen mit unterschiedlichen Daten ein.
- HINWEIS: In den obigen Abschnitten ist "große Anzahl" und "unterschiedliche Daten" eine Vorsichtsmaßnahme, um sicherzustellen, dass Ihre Abfrage selektiv genug ist . Andernfalls kann der Optimierer entscheiden, Ihren Index in keinem Fall zu verwenden.
- Generieren Sie einen Abfrageplan für Ihre Abfrage (einmal mit einem Index in der Spalte Datum und einmal ohne).
- Sie können auch STATISTICS IO verwenden, um den Unterschied anzuzeigen.
- Wenn Sie über genügend Testdaten verfügen, ist der Unterschied leicht erkennbar.
Sobald Sie die Beweise haben, schlage ich vor, dass Sie sie mit dem DBA aufnehmen. Lassen Sie sich jedoch nicht auf einen Streit ein. Zeigen Sie einfach den Test und die Daten, die zeigen, dass der Index verwendet wird.
Der Punkt ist, dass Sie nicht gezwungen werden möchten, sich nach hinten zu beugen, um nicht vorhandene Probleme zu vermeiden.
Glücklicherweise ist es in dem von Ihnen demonstrierten Fall kein Problem, die Funktionen außerhalb der Abfrage zu verschieben. Z.B
DECLARE @FromDate date ='inputdate',
@ToDate date = DATEADD(day, 1, @FromDate)
In der Tat kann das Obige auf lange Sicht sogar wartbarer sein.
Es wird jedoch eine Zeit kommen, in der Sie etwas haben, das nicht trivial nach den Wünschen des DBA geändert werden kann. Sowie:
--Granted this probably belongs in a JOIN clause, but is primarily for illustrative purposes.
--Also the issue of sargability applies just as much to JOIN clauses as WHERE clauses
WHERE a.date >= b.date
AND a.date < DATEADD(day, 1, b.date)
Die einzige Möglichkeit, diese Funktion aus der WHERE-Klausel herauszuholen, besteht darin, eine andere Spalte vorab zu berechnen b.NextDay
. Genau aus diesem Grund benötigen Sie die Datenbankadministratoren, um die Sargabilität richtig zu verstehen. Dh das oben genannte:
- Wäre in der Lage, einen Index auf zu nutzen
a.date
.
- Aber nicht in der Lage sein, einen Index zu nutzen
b.date
.
- Auf die selektivste Spalte / den selektivsten Index sollte also keine Funktion angewendet werden, auf die andere.
- Der Versuch, eine Lösung ohne eine Funktion in der WHERE-Klausel zu hacken, verringert sowohl die Wartbarkeit als auch die Leistung.
Wenn Sie wirklich kein Buy-In von den DBAs erhalten können, funktioniert möglicherweise Folgendes und umgeht deren Regeln für den Frachtkult:
;WITH CTE_B AS (
SELECT b.Date, DATEADD(day, 1, b.DATE) AS NextDay
FROM b
)
SELECT ...
WHERE a.Date >= CTE_B.Date
AND a.Date < CTE_B.NextDay
Der Optimierer wird dies mit ziemlicher Sicherheit auf die gleiche Weise optimieren, als ob die Funktion in der WHERE
Klausel enthalten wäre, sodass Sie keinen Leistungsverlust erhalten sollten. Aber es ist sicherlich eine unnötige Verringerung der Wartbarkeit.
BETWEEN
mit Datumsangaben verwenden, aber das ist ein anderes, nicht verwandtes Problem.) Sie zeigen uns jedoch nur eine Abfrage. Wenn Sie Dutzende von Abfragen mit nicht sargierbaren Bedingungen und Funktionsaufrufen haben, haben sie möglicherweise die tatsächlich sargable verpasst.