2010-01-25 10 views
10

Ich habe einen riesigen Tisch, mit dem ich arbeiten kann. Ich möchte überprüfen, ob es einige Datensätze gibt, deren Parent_id meinem übergebenen Wert entspricht. derzeit, was ich dies implementieren, ist mit "wählen Sie Anzahl (*) aus meiner Tabelle, wo parent_id =: id"; Wenn das Ergebnis> 0 ist, bedeutet das, dass sie existieren.Der schnellste Weg zu überprüfen, ob einige Datensätze in einer Datenbanktabelle sind?

Da dies eine sehr große Tabelle ist, und mir egal ist, was die genaue Anzahl der Datensätze ist, möchte ich nur wissen, ob es existiert, also denke ich count (*) ist ein bisschen ineffizient.

Wie kann ich diese Anforderung am schnellsten umsetzen? Ich bin mit Oracle 10.

#

Nach Tipps & Tricks https://www.hibernate.org/118.html#A2

es so zu schreiben, schlägt vor, in den Ruhezustand:

Integer count = (Integer) session.createQuery ("select count (*) from .... "). uniqueResult();

Ich weiß nicht, was ist die Magie von uniqueResult() hier? Warum macht es das schnell?

Vergleichen Sie mit "wählen Sie 1 aus meiner Tabelle, wo parent_id = passingId und rowrum < 2", die effizienter ist?

Antwort

9

Eine Abfrage vorhanden ist, die man für gehen, wenn Sie in der Anzahl der Datensätze nicht interessiert sind:

select 'Y' from dual where exists (select 1 from mytable where parent_id = :id) 

Dies wird zurückkehren ‚Y‘, wenn ein Datensatz vorhanden ist und nichts anderes.

[In Bezug auf Ihre Frage zu Hibernate's "uniqueResult" - all dies ist ein einzelnes Objekt zurückgeben, wenn nur ein Objekt zurückgegeben wird - anstelle eines Satzes mit 1 Objekt. . Wenn mehrere Ergebnisse zurückgegeben werden die Methode eine Ausnahme wirft]

+0

Sie brauchen nicht einmal DUAL abzufragen - wählen Sie Y aus mytable aus, wobei parent_id =: id AND ROWNUM = 1' identische Ergebnisse liefert. –

+0

Yep - mag einfach nicht "ROWNUM = 1" - fühlt sich nicht so transparent an wie eine EXISTS-Abfrage. Nur ich auch. –

2

Zuerst benötigen Sie einen Index auf mytable.parent_id.

Das sollte Ihre Abfrage schnell genug machen, auch für große Tabellen (es sei denn, es gibt auch viele Zeilen mit der gleichen parent_id).

Wenn nicht, könnten Sie

select 1 from mytable where parent_id = :id and rownum < 2 

schreiben, die überhaupt eine einzelne Zeile mit 1, oder keine Zeile zurückkehren würde. Es muss die Zeilen nicht zählen, sondern nur einen finden und dann beenden. Aber das ist Oracle-spezifische SQL (wegen Rownum), und Sie sollten eher nicht.

+0

+1 für die Indexempfehlung –

+2

Ich würde für eine EXISTS-Abfrage gehen ich denke - transparenter für die Anforderung: Wählen Sie 1 aus Dual, wo vorhanden ist (wählen Sie 1 aus Mytable wo parent_id =: id) –

0

Für DB2 gibt es so etwas wie select * from mytable where parent_id = ? fetch first 1 row only. Ich nehme an, dass etwas Ähnliches für Orakel existiert.

+1

Alle SQl-Dialekte unterscheiden sich - Sie können nicht davon ausgehen, dass es ähnliche Dinge gibt, z Oracle hat rownum, was es in Sybase nicht gibt, und ich denke, in DB2 – Mark

+2

ist das rownum-Konzept das, was ich "ähnlich" nennen würde, weil es den gleichen Anwendungsfall abdeckt, dh die obersten n Datensätze (http: //www.petefreitag. com/item/59.cfm) – bertolami

+0

re: top n. Ein Problem mit rownum ist, dass es vor dem Sortieren ausgewertet wird, also ist es nicht wirklich "top" n. – Thilo

4

Es gibt keinen wirklichen Unterschied zwischen:

select 'y' 
    from dual 
where exists (select 1 
       from child_table 
       where parent_key = :somevalue) 

und

select 'y' 
    from mytable 
where parent_key = :somevalue 
    and rownum = 1; 

... zumindest in Oracle10gR2 und höher. Oracle ist clever genug in dieser Version, um eine FAST DUAL-Operation auszuführen, bei der es jede echte Aktivität gegen es ausnutzt. Die zweite Abfrage wäre einfacher zu portieren, wenn dies jemals in Betracht gezogen wird.

Das eigentliche Leistungsmerkmal ist, ob die Spalte parent_key indiziert ist oder nicht. Wenn es nicht ist, dann sollten Sie so etwas wie laufen:

select 'y' 
    from dual 
where exists (select 1 
       from parent_able 
       where parent_key = :somevalue) 
5

select count (*) sollte lighteningly schnell sein, wenn Sie einen Index haben, und wenn Sie dies nicht tun, so dass die Datenbank zum Abbruch nach dem ersten Match gewonnen Es hilft nicht viel.

Aber da Sie gefragt:

boolean exists = session.createQuery("select parent_id from Entity where parent_id=?") 
         .setParameter(...) 
         .setMaxResults(1) 
         .uniqueResult() 
       != null; 

(Einige Syntaxfehler zu erwarten, da ich gegen auf diesem Computer zu testen, keine Hibernate haben)

Für Oracle wird maxResults übersetzt in rownum durch Winterschlaf.

Was uniqueResult() tut, lesen Sie ihre JavaDoc! Die Verwendung von uniqueResult anstelle von list() hat keine Auswirkungen auf die Leistung. wenn ich mich richtig erinnere, die Implementierung von uniqueResult Delegaten zu list().

+0

+1 für setMaxResults – Thilo

0

wird diese Abfrage 1 zurück, wenn Datensatz anders und 0 existiert:

SELECT COUNT(1) FROM (SELECT 1 FROM mytable WHERE ROWNUM < 2); 

Es helfen könnte, wenn Sie Tabellendaten Statistiken benötigen, Größe und jedes Performance-Problem, unabhängig Tabelle zu überprüfen.

Verwandte Themen