2009-10-08 3 views
16

Ich habe dieses eine Weile schon gekämpft. Ich habe eine gespeicherte Prozedur, die 3 Parameter verwendet, die zum Filtern verwendet werden. Wenn ein bestimmter Wert übergeben wird, möchte ich darauf filtern. Wenn -1 übergeben wird, gib mir alles.T-SQL Where Clause Fall Anweisung Optimierung (optionale Parameter zu StoredProc)

Ich habe es versucht, die folgenden zwei Möglichkeiten:

Erster Weg:

SELECT field1, field2...etc 
FROM my_view 
WHERE 
parm1 = CASE WHEN @PARM1= -1 THEN parm1 ELSE @PARM1 END 
AND parm2 = CASE WHEN @PARM2 = -1 THEN parm2 ELSE @PARM2 END 
AND parm3 = CASE WHEN @PARM3 = -1 THEN parm3 ELSE @PARM3 END 

Zweiter Weg:

SELECT field1, field2...etc 
FROM my_view 
WHERE 
(@PARM1 = -1 OR parm1 = @PARM1) 
AND (@PARM2 = -1 OR parm2 = @PARM2) 
AND (@PARM3 = -1 OR parm3 = @PARM3) 

ich irgendwo gelesen, dass der zweite Weg kurzgeschlossen wird und nie Eval der zweite Teil wenn wahr. Mein Datenbankadministrator hat angegeben, dass ein Tabellenscan erzwungen wird. Ich habe das nicht verifiziert, aber es scheint in einigen Fällen langsamer zu laufen.

Die Haupttabelle, dass diese Ansicht von wählt hat irgendwo rund 1,5 Millionen Datensätze, und die Ansicht Erlös etwa 15 andere Tabellen verknüpfen auf ein paar anderen Informationen zu sammeln.

Beide Methoden sind langsam ... mich von einem Augenblick nehmen, um überall 2-40 Sekunden, was in meiner Situation völlig inakzeptabel ist.

Gibt es eine bessere Art und Weise, die es nicht in jedem einzelnen Fall spezifischer Bruch mit sich bringt nach unten vs -1?

Jede Hilfe wird geschätzt. Vielen Dank.

Antwort

6

Ich habe irgendwo gelesen, dass der zweite Weg Kurzschluss und nie den zweiten Teil eval wenn wahr. Mein Datenbankadministrator hat angegeben, dass ein Tabellenscan erzwungen wird.

Sie lesen falsch; es wird nicht Kurzschluss. Ihr DBA hat Recht; Es wird mit dem Abfrageoptimierer nicht gut funktionieren und wahrscheinlich einen Tabellenscan erzwingen.

Die erste Option ist ungefähr so ​​gut wie es geht. Ihre Möglichkeiten, Dinge zu verbessern, sind dynamische SQL oder eine lange gespeicherte Prozedur mit jeder möglichen Kombination von Filterspalten, so dass Sie unabhängige Abfragepläne erhalten. Sie können auch versuchen, die Option "WITH RECOMPILE" zu verwenden, aber ich denke nicht, dass es Ihnen helfen wird.

+0

Verdammt. Beat mich dazu. +1 :) – DVK

+1

Die erste Option liefert nicht unbedingt die gleichen Ergebnisse wie die zweite. Wenn Sie Zeilen in Ihrer Tabelle mit NULL-Werten haben, werden sie von der Abfrage "Option 1" NICHT zurückgegeben. Zum Beispiel .... Wählen Sie * Aus Tabelle Wobei NullableColumn = NullableColumn –

+0

Alle drei parms sind NICHT NULL, das ist also kein Problem in diesem Fall. Sieht so aus, als ob ich bei Option 1 steckengeblieben wäre. – IronicMuffin

0

Keine andere Art, wie ich denken kann, dann tun:

WHERE

(myCASE null oder myCASE = @MyCaseParameter) UND ....

Die zweite ist einfacher und lesbar für die Entwickler, wenn Sie mich fragen.

+1

Es ist auch langsam wie Melasse. Benutze es nicht. –

+0

@Joel hast du etwas, um das zu sichern? Nicht, dass ich dich bezweifle, ich suche nur nach harten Daten auf die eine oder andere Weise. – Jonas

+0

Ich habe zwei Indikatoren, dass die zweite Methode einen Tabellenscan erzwingen kann, und das ist keine gute Sache mit 1,5 Millionen Datensätzen. – IronicMuffin

2

Wenn Sie in einem Null-Wert übergeben, wenn Sie alles wünschen, dann können Sie Ihre where-Klausel schreiben, wie

Where colName = IsNull(@Paramater, ColName) 

Diese im Grunde gleich wie die erste Methode ist ... wird es, solange die Spalte arbeiten selbst ist nicht nullable ... Null Werte IN die Spalte wird es leicht durcheinander bringen.

Der einzige Ansatz, es zu beschleunigen ist ein Index für die Spalte hinzuzufügen, wird in der Where-Klausel gefiltert auf. Gibt es schon einen?Wenn nicht, wird dies zu einer dramatischen Verbesserung führen.

+0

Glaubst du, dass dies alles beschleunigen wird? Es scheint, als ob es im Grunde die gleiche Operation ist, aber Null statt -1 zu überprüfen. Ist IsNull effizienter als ein CASE? – IronicMuffin

+0

@IronicMuffin, (Ich mag Ihren Spitznamen) Nein, Sie sind genau richtig, das ist Äquivalenz mit der ersten Methode ... –

5

Wenn Sie SQL Server 2005 oder höher ausführen, können Sie IFs verwenden, um mehrere Versionen der Abfrage mit dem entsprechenden WHERE zu erstellen, sodass ein Index verwendet werden kann. Jeder Abfrageplan wird in den Abfragecache gestellt.

auch, hier ist ein sehr umfassender Artikel zu diesem Thema:

Dynamic Search Conditions in T-SQL by Erland Sommarskog

es deckt all Themen und Methoden zu versuchen, Abfragen mit mehreren optionalen Suchbedingungen

hier zu schreiben ist der Tisch des Inhalts:

 
    Introduction 
     The Case Study: Searching Orders 
     The Northgale Database 
    Dynamic SQL 
     Introduction 
     Using sp_executesql 
     Using the CLR 
     Using EXEC() 
     When Caching Is Not Really What You Want 
    Static SQL 
     Introduction 
     x = @x OR @x IS NULL 
     Using IF statements 
     Umachandar's Bag of Tricks 
     Using Temp Tables 
     x = @x AND @x IS NOT NULL 
     Handling Complex Conditions 
    Hybrid Solutions – Using both Static and Dynamic SQL 
     Using Views 
     Using Inline Table Functions 
    Conclusion 
    Feedback and Acknowledgements 
    Revision History
+0

+1 für die Verknüpfung von etwas von Mr Sommarskog –

+0

Lesezeichen ... danke. Wir verwenden eine Mischung aus Servern 2000/2005, leider ist dieser 2000. – IronicMuffin

+0

der Artikel deckt zahlreiche Möglichkeiten, variable Suchbedingungen zu behandeln, die IFs ist nur einer –

0

SQL 2008 und später machen einige Verbesserungen zur Optimierung für Dinge wie (MyCase IS NULL OR MyCase = @MyCaseParameter) AND ....

Wenn Sie aktualisieren können, und wenn Sie ein OPTION (RECOMPILE) hinzufügen anständigen perf für alle möglichen param Kombinationen zu erhalten (dies ist eine Situation, wo es kein einziger Plan ist, die für alle möglichen param Kombinationen gut ist), können Sie feststellen, dass Das funktioniert gut.

http://blogs.msdn.com/b/bartd/archive/2009/05/03/sometimes-the-simplest-solution-isn-t-the-best-solution-the-all-in-one-search-query.aspx