# Wirkliche Zeilenanzahl eines ResultSets ermitteln



## Pavoo (19. Dez 2006)

Moin Moin,

ich bin bei der Erstellung einer Applikation (JDBC auf Oracle) auf folgendes Problem gestoßen:
Ich kann beliebige SQLStatements gegen die DB absetzen, sollte aber die maximale Zeilenausgabe auf 1000 beschränken.

Also habe ich ganz einfach (vereinfachte Form) gelöst:


```
....

Connection connection .... ;l
Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);

statement.setMaxRows(1000);

OracleDBResultSet result = new OracleDBResultSet(statement.executeQuery("SELECT * FROM ALL_OBJECTS"));

....
```

Soweit so gut ich bekomme mein result und kann es weiterverarbeiten.
Ich möchte aber wissen ob es eventuell mehr Zeilen (Results) gibt ,die mir aber auf Grund meiner Begrenzung von 1000 Zeilen nicht angezeigt werden?

Und wie das funktioniert habe ich leider noch nicht herraus gefunden und hoffe auf einen Vorschlag von euch.
Vielen Dank.


----------



## DaKo (19. Dez 2006)

select count(*) from all_objects


----------



## Pavoo (19. Dez 2006)

Naja, das war nicht gerade das worauf ich hinaus wollte 

man bedenke nur mal, wenn eine Selektion 10 min dauert.....

dann noch der Count.... 

ich glaube die Fachabteilung läd mich zur nächsten Weihnachtsfeier nicht mehr ein.

Ich habe da an eine Interne Implementierung der Statement , ResultSets || ResultSetMetaData gedacht, die es ermöglicht diese Information zu bekommen.


----------



## Pavoo (19. Dez 2006)

Naja, das war nicht gerade das worauf ich hinaus wollte 

man bedenke nur mal, wenn eine Selektion 10 min dauert.....

dann noch der Count.... 

ich glaube die Fachabteilung läd mich zur nächsten Weihnachtsfeier nicht mehr ein.

Ich habe da an eine Interne Implementierung der Statement , ResultSets o.  ResultSetMetaData gedacht, die es ermöglicht diese Information zu bekommen.


----------



## DaKo (19. Dez 2006)

> man bedenke nur mal, wenn eine Selektion 10 min dauert.....


 :shock: 

Entweder machst du was falsch oder es sind *definitiv* mehr als 1000 Zeilen.


----------



## Pavoo (19. Dez 2006)

Naja wir arbeiten hier mit mehreren Millionen DS und das ist absolut nicht ungewöhnlich das eine Selektionen mehrere Minuten dauern können.


----------



## DaKo (19. Dez 2006)

> ...SELECT * FROM ALL_OBJECTS..



Dann sind *das* mehr als 1000 Zeilen.
Somit versteh ich dein Problem nicht mehr  ???:L


----------



## Pavoo (19. Dez 2006)

Ok vielleicht war meine Frage unverständlich formuliert. Die Anzahl der Oracle Objekt interessiert mich herzlich wenig, sie sollte nur als Beispiel dienen.

Natürlich sind die Statements nicht starr im Code verankert sondern dynamisch und natürlich handelt es sich bei den Statements die später abgesetzt werden nicht um simple SQLs die über eine Tabelle iterieren.
Die können das volle Programm enthalten ([JOINS]*, [Subselects]*, Models, [DB-Links]*, [Groupings]* etc.)

Deswegen strebe ich eine Lösung auf Treiberebene an und nicht ein wiederholtes SELECT auf die DB.


----------



## DaKo (19. Dez 2006)

:idea: 

Problem verstanden 

Aber leider keine Lösung parat   

Werde mal drüber nachdenken


----------



## Pavoo (19. Dez 2006)

alles klar , trotzdem wieder etwas dazu gelernt:

"Fragen richtig und präzise formulieren!"

 Danke


----------



## bronks (19. Dez 2006)

Pavoo hat gesagt.:
			
		

> ... Die können das volle Programm enthalten ([JOINS]*, [Subselects]*, Models, [DB-Links]*, [Groupings]* etc.)
> ...


Das volle Programm wird m.E. total verkehrt eingesetzt sein, denn für lachhafte nur 1000 Zeilen kann man keine 10 Minuten opfern.

Auch wenn die Daten aus einer unmenge an Tabellen gelesen werden, dann hat man mit PL/SQL Mittel die Angelegenheit elegant und performant zu lösen. 

Rechne Dir mit einem Taschenrechner aus, wieviele Zugriffe für die genannten 1000 Zeilen nötig sind und dann Schätze ab, wie lange das dauernd dürfte, aber 10 Minuten sind bei einer gesunden Datenbank unter allen Umständen einfach zu viel. Mit richtigem Einsatz von PL wirst Du auf die geschätze Dauer der Zugriffe, also auf wenige Sekunden kommen.


----------



## Pavoo (19. Dez 2006)

Moin moin,

also ich möchte nicht darüber diskutieren,  bzw. beurteilen wie fähig unsere Fachabteilung ist perfomante Statements zu schreiben (das würde ich mir auch nicht anmaßen).
Ehrlich gesagt habe ich da auch keinen Einfluß darauf, welche Statements abgesetzt werden.
Ich schreibe eine Applikation die SQLStatements ausführt!

Auch wenn ein Statement 3min, 1min oder 30 sek. läuft ein zusätzlicher Count bedeutet immer eine Verminderung der Performance.

Ich find es durchweg naiv davon auszugehen, dass jedes Statement durch "guten Code (PL/SQL)" binnen Sekunden ausgeführt ist. Wenn Sie das können (auch das maße ich mir nicht an zu beurteilen), dann Respekt. Sie können aber nicht davon ausgehen, das alle diese Fähigkeit besitzen und außerdem beantwortet es nicht meine Frage.

Auch die Anzahl der Zeilen ist nicht lächerlich sondern irrelevant. 
Ein Count liefert 1 Zeile zurück, und selbst das kann Minuten dauern.... hängt von mehrern Faktoren ab!

Und wenn ich zB. eine Volltextsuche über Namen und der Straße in einer Kundentabelle ausführe die aus mehreren Millionen DS besteht und auch noch alle Vertragsdaten Joinen muss..., vieleicht noch ein Group By roll Up über das Land...
Um letztendlich 10 DS zu erhalten.... kann es dauern.
Oder jemand schreibt ein Statement mit 50.000 Unions über Tabellen in verteilten Datenbanken.
Da habe ich keinen Einfluß darauf, ich gebe halt nur 1000 Zeilen aus (um die Performance meiner Applikation zu gewährleisten).

Zur Info: Das hier ist meinens Erachtens kein Forum für SQL - PL/ SQL, deswegen beschränkt sich meine Frage auch nicht darauf wie man sinnige SQL-Statements schreibt. 
*
Sondern ob es möglich ist mit JAVA/JDBC herrauszufinden, ob noch weitere Records (über die MaxRows hinaus) vorhanden sind.  *

Vielen Dank . :wink:


----------



## SlaterB (19. Dez 2006)

denke doch mal logisch, da scheint es trotz hochtrabender Formulierung zu hapern 

Java oder JDBC wissen überhaupt nix davon, wenn überhaupt, dann die DB, die die Anfrage auswertet,

und eine Anfrage auf 2000 Datensätze, die 20 Min. dauert,
dauert mit maxRows 1000 nur 10 Min. (bei angenommener gleichverteilter Suche usw.),

bevor also nicht 20 Min. vergehen kann niemand auf der Welt sagen, wieviele Ergebnisse vorhanden sind,
ob dann alle 2000, nur 1000 oder genau ein Datensatz (mit der Anzahl) übergeben werden ist unerheblich,

-----

die einzig relevante Frage ist:
kann eine DB 20 Min. rechnen, die Anzahl zurückgeben (z.B. 2000) und dann in einer zweiten Anfrage sofort die ersten 1000 davon zurückliefern, ohne wieder 20 Min. zu suchen,

also ein Frage des Cachings/ temporäre Tabellen oder so,
das ist was für ein Datenbank-Forum,

-----

Java/ JDBC kann nix damit zu tun haben,
die könnten das natürlich in zwei Schritten machen, wenn sie alle 2000 Results laden,
aber das ist ja eine triviale Erkenntnis, dann sind ja eh alle Ergebnisse im Speicher vorhanden


----------



## AlArenal (19. Dez 2006)

SlaterB hat gesagt.:
			
		

> bevor also nicht 20 Min. vergehen kann niemand auf der Welt sagen, wieviele Ergebnisse vorhanden sind,
> ob dann alle 2000, nur 1000 oder genau ein Datensatz (mit der Anzahl) übergeben werden ist unerheblich



Korrekt. Die Datenbank die schon vor der Query weiß, was nach Abarbeitung der Query rauskommt, hat noch niemand erfunden.

P.S.:
Muss mal ne Mail an Larry Ellison schreiben und fragen, was ihm die Idee wert ist...


----------



## Pavoo (19. Dez 2006)

Es ist mir natürlich klar das nur die DB weiß, wieviele DS es gibt und zwar nachdem das Statement ausgeführt wurde.:roll: 
 Das will ich aber auch nicht wissen.: Sondern ob noch weitere DS exsistieren (true/false).

Damit ich eine Information an den Benutzer geben kann.

Da ich allerdings die Implementierung von JDBC nicht kenne, finde ich nicht, dass es an fehlender Logik hapert.
Vielleicht selektiert JDBC ja maxRows+1 um genau diese Information zu erhalten.
Vielleicht muss JDBC aber auch alles selektieren und gibt nur maxRow an den Client zurück.
... ich weiß es nicht.

Deswegen frage ich ja 

Aber egal ich vertraue da mal auf Ihre Fachkenntnis und nehme es als "nicht möglich" hin. 

Danke


----------



## bronks (19. Dez 2006)

Über MaxRows hinaus kommst Du mit JDBC nicht, denn JDBC hat von der tatsächlichen Anzahl der Sätze keine Ahnung. Mit MaxRows sorgst Du nur dafür, daß Deine App nicht platz. Die DB muß trotzdem immer die ganze Arbeit machen und alle Daten bereitstellen.

Schade, daß Du keinen Einfluß darauf hast, denn da könnte man sicher viel bewegen. Software ist das einzige, wo man die meiste Theorie 1:1 in Praxis umsetzen kann und genau deshalb Summiere ich die Anzahl der erwarteten Zugriffe immer, um nicht ein Bild über erwartete Laufzeiten zu bilden.

In Deinem o.g. Beispiel mit der Volltextsuche zeigst Du ja wo es hakt: Du joinst einfach alle Vertragsdaten. Den Join bekommst Du vom Server nicht geschenkt. Das dauert und vor allem dann, wenn kein passender Index da ist.

Meine Kalkulation dazu: 
4 Mio. Sätze in Volltextsuche: 3 Sek.
Zu den gefundenen 4 Kunden die Vertragsdaten holen: Ein paar Milis
Evtl. noch ein paar Details: Weitere paar Milis


----------



## SlaterB (19. Dez 2006)

1001 Daten abzufragen ist doch ein schlauer Weg,
dauert nur 0.1% länger und enthält doch die Info ob mehr als 1000 oder maximal 1000 Datensätze da sind


----------



## Guest (19. Dez 2006)

Habe ich mir schon gedacht, dass alles selektiert wird.
Das mit dem Beispiel war auch nur ein Beispiel, wie gesagt ich habe keine Ahnung was für Statements später abgesetzt werden. 
Ich wollte nur möglichst vermeiden ein zweites Mal ein Select abzusetzen, um zu ermitteln ob noch mehr DS vorhanden sind. 

Aber die Information ist hilfreich, Danke


----------



## Pavoo (19. Dez 2006)

SlaterB hat gesagt.:
			
		

> 1001 Daten abzufragen ist doch ein schlauer Weg,
> dauert nur 0.1% länger und enthält doch die Info ob mehr als 1000 oder maximal 1000 Datensätze da sind




ja schon bedeutet aber das ich an bestehenden Code ran muss und bei der iterativen Verarbeitung des Results, immer einen Count <= 1000 laufen lassen muss 

Aber wahrscheinlich ist das der einzige Weg.


----------



## KSG9|sebastian (19. Dez 2006)

Wie oben schon geschrieben:
Du willst maximal X Datensätze anzeigen

- Select mit Limit 0, X+1 ausführen
- Beim durchlaufen des RS nen counter o.ä. mitlaufen lassen

Wenn counter = x+1 dann "Weitere Datensätze vorhanden".
Das ist wohl der einzige praktikable Weg. Und vor allem wirst du nicht merklich an Performance verlieren wegen einem Datensatz hin oder her.


----------



## Pavoo (19. Dez 2006)

LIMIT >> MySQL

ja aber so ähnlich werde ich es lösen.


----------



## bronks (19. Dez 2006)

Pavoo hat gesagt.:
			
		

> ... ja schon bedeutet aber das ich an bestehenden Code ran muss und bei der iterativen Verarbeitung des Results, immer einen Count <= 1000 laufen lassen muss  ...


Ahh ich meine verstanden zu haben: Dein Programm ist dafür da, daß jemand sein Query reinklopft und dann die ersten 1000 Zeilen zur Ansicht stehen?

Am raffiniertesten wäre es m.E. alle erhaltenen Daten temporär in eine Textdatei zu schreiben und diese dem User anzuzeigen. Zu dem gibt es Statement- und ResultSetTypen, in denen man blättern kann, ohne daß die JavaApp die Daten halten muß. Somit könnte man das ressourcensparend umsetzen.


----------



## Pavoo (19. Dez 2006)

Arbeitsanweisung:

"....1000 Zeilen und Info ob weitere DS vorhanden anzeigen...."


----------

