2010-11-19 4 views
1

Ich habe eine Abfrage wie:SQL-Abfrage mit where-Klausel Ausführung

(q1) 
select a,b,c,d from abc 
where param='x' 

union 

(q2) 
select e,f,g,h from abc 
where param='y' 

Ich würde, wenn der Wert von <param>='y' wissen will QUERY1 ausgeführt werden soll ?? Dies ist, weil das recodset "abc" sehr sehr groß ist und tatsächliche Abfrage umfasst 5-6 Gewerkschaften auf den gleichen Parameter (Sie können sehen, dass nur eine Abfrage Daten auf einmal benötigt wird). Wenn also die Daten von allen Abfragen abgerufen werden und die where-Klausel gefiltert wird, wäre das ein großer Aufwand, während, wenn vorher gefiltert, nur eine von 5 Abfragen tatsächlich ausgeführt wird.

Dank Himanshu

+0

Außerdem verwende ich Oracle DB (ID, die die Antwort bewirkt) – Himz

+1

Versuchen Sie, mehr über grundlegende SQL-Konzepte zu lesen; In der Zwischenzeit können Sie für jedes SQL EXPLAIN ... ausgeben und das RDBMS zeigt Ihnen einen Plan (der Sie einige weitere Konzepte lernen lassen muss, aber auf lange Sicht ist es wirklich nützlich zu wissen, ob Sie Feinheiten von SQL vs reale Datenzugriffspfade und Algorithmen). – Unreason

+0

Ich gehe diesen Link. Dieser klärt über Bind-Variablen http://www.akadia.com/services/ora_bind_variables.html – Himz

Antwort

2

Wenn Sie so etwas wie

where 1 = 2 

schreiben, die ohne Berührung der Datenbank ausgewertet werden kann, dann wird Oracle klug genug sein, um die Tabellen zu überspringen erreichbar.

Dies sollte sogar mit Bind-Variablen arbeiten.

where ? = ? 

Natürlich, sobald Spalten beteiligt sind, muss es gehen, um die Daten zu betrachten.

+0

Danke, Es ist eine Bind-Variable. – Himz

+0

Das bedeutet, ich kann so viele Gewerkschaften auf die Art und Weise verwenden, ohne viel Overhead zu haben? – Himz

+1

Der Abfrageoptimierer sollte in der Lage sein, toten Code in Ihrer Abfrage zu finden und zu verwerfen. Overhead im Vergleich zu was? Es wird noch leichter, wenn Sie den nutzlosen Teil selbst beseitigen. – Thilo

2

Wenn 'param' eine Spalte in abc ist, würde es sehr hilfreich sein, wenn Sie diese Spalte indizieren.

Die größte Auswirkung auf die Leistung in Ihrer Abfrage ist jedoch wahrscheinlich die "Union", da Oracle doppelte Zeilen herausfiltern muss. Abhängig von der Größe Ihrer Ergebnismenge ist dies eine ziemlich schwere Operation (Sortieren, Entfernen von Duplikaten). Wenn Sie nicht mit doppelten Ergebnissen betroffen (oder wenn sie wegen der Definition der Abfragen einfach unmöglich sind), verwenden Gewerkschaft alle ':

select a,b,c,d from abc 
union all 
select e,f,g,h from abc 
+0

ist eine Bind-Variable (keine Spalte) – Himz

+0

Abfrage ist so, dass nur eine von allen Unio-Daten abhängig von dem Wert von abgerufen wird. – Himz

+4

Es scheint mir eine bessere Lösung zu sein, die Software so zu ändern, dass sie die richtige Abfrage ausführt, anstatt die Datenbank basierend auf einem Bindeparameter herauszufinden. Ist das möglich? –

1

Meiner Meinung nach ist diese faul Programmierung und Sie versuchen, um die Datenbank dazu zu bringen, die Aufgabe der Anwendung auszuführen. Eine einfache "Wenn" -Anweisung mit einer Reihe von Verkettungen ist alles was Sie brauchen.

+0

Ich denke, es ist anmaßend zu sagen, es ist "faul" - Sie kennen nicht den Kontext, in dem diese Abfrage erforderlich ist. Zum einen könnte es in einem Kontext sein, der PL/SQL nicht zulässt. Und wo wird gesagt, dass das, was man macht, der Job der "Anwendung" sein muss? –

2
select * 
from (
select 1 INDICATOR, 
     a, b, c 
from abc 
union all 
select 2 INDICATOR, 
     a, b, c 
from abc) 
where indicator = 1; 

Dies wird die zweite Abfrage in der Union nicht ausführen. Wie Sie im Ausführungsplan sehen können, gibt es einen Filter, der sagt "Null ist nicht null". Allerdings gibt es bei vielen Gewerkschaften einen erheblichen Overhead.

0

Die Frage legt nahe, dass Sie zwei vollständige Tabellensuchen über den Datensatz vermeiden möchten. Diese Technik könnte Ihnen helfen.

WITH 
base AS 
(
    SELECT a,b,c,d,e,f,g,h FROM abc -- all columns of interest 
    WHERE param IN ('x', 'y')  -- all rows of interest 
), 
q1 AS 
(
    select a,b,c,d from base  -- one specific subset 
    where param='x' 
), 
q2 AS 
(
    select e,f,g,h from base  -- the other specific subset 
    where param='y' 
) 
SELECT a,b,c,d FROM abc    -- then the union of the sets 

UNION 

SELECT e,f,g,h FROM abc    -- that you are interested in. 

Wie Sie Lookups auf param tun, würde ein Index von großem Wert sein, so dass die FULL TABLE SCAN durch einen weniger kostspieligen INDEX Scan ersetzt werden.

Wenn die Menge unterschiedlicher Werte in param klein ist, kann es von Vorteil sein, histograms zu erstellen.

Wie in allen Dingen Oracle, kann Ihre Laufleistung variieren.

Ich wäre interessiert zu hören, wie alles für dich herauskommt.

+0

Danke. Ich hatte mich entschlossen, mit meiner aktuellen Implementierung zu arbeiten. Hoffe, dass dieses Ding für mich richtig funktioniert. – Himz

0

Wie andere darauf hingewiesen haben, entfernt Oracle nach der Auswertung der Bind-Variablen tote Codezweige aus Ihrer Abfrage. Sie können die Union durch "union all" ersetzen (nicht dass es trotzdem wichtig wäre), aber die Absicht des Entwicklers wird deutlicher dargestellt (ich, der Entwickler, erwartete hier keine Duplikate).

Eine offene Frage (für mich jedenfalls) ist: Können Sie sicher wissen, dass der Datentyp von "a" mit "e" übereinstimmt und "b" mit "f" usw. übereinstimmt?

Eigentlich habe ich das nie selbst umgesetzt, nur gelesen, damit jemand validieren will, was ich sage. Ein völlig anderer Ansatz könnte jedoch darin bestehen, eine gespeicherte Prozedur zu erstellen, die den Parameter übernimmt. Die Prozedur würde einen Cursor für jeden erwarteten Wert von param haben. Dann können Sie (IF) den Wert des Parameters testen und einen Ref-Cursor zurückgeben.

+0

Ich verstehe nicht, was Sie mit Datentyp übereinstimmen. In Gewerkschaften alle Spalten sollten gleich sein und wenn wir nicht brauchen eine bestimmte Spalte wir tun "null als ".Also ist "a" genauso wie "e" und "b" ist gleich "f". Ich kann keine gespeicherte Prozedur erstellen. Kann nur SQL verwenden. Danke – Himz

+0

Sie haben DDL nicht geteilt, also konnte ich nicht wissen. – Ronnis