Uebergabe langer Liste an Datenbank

Uebergabe langer Liste an Datenbank

am 22.02.2006 10:33:57 von unknown

Post removed (X-No-Archive: yes)

Re: Uebergabe langer Liste an Datenbank

am 22.02.2006 10:54:51 von Fabian Schladitz

Rainer Gauweiler schrieb:
> ich habe ein Array, das eine lange Liste mit Primärschlüsseln enthä=
lt. Nun
> brauche ich die Daten, die zu diesen Schlüsseln gehören.

Die Auswahl der Elemente geschieht im PHP?
Also auch keine Möglichkeit eine VIEW oder SUBSELECT zu nutzten?

> Der Standardweg der mir einfällt ist eine Schleife, die entweder laut=
er
> einzelne SQLs abschickt, oder eine where-Klausel zusammenbaut:
>=20
> foreach($feld as $nr) {
> $ergebnis[]=3D$db->select("select daten from tabelle where nr=3D$nr);
> }
>=20
> foreach($feld as $nr) {
> $in-kette.=3D$nr.",";
> $or-kette.=3D"nr=3D$nr or ";
> }
> $ergebnis=3D$db->select("select daten from tabelle where $or-kette");
> $ergebnis=3D$db->select("select daten from tabelle where nr in ($in-ket=
te));
>=20
> Feinheiten wie überflüssige or und , bzw Möglichkeiten sowas mit =
implode zu
> machen ignoriere ich jetzt mal.
>=20
> Mein eigentliches Problem: Sowohl oracle als auch db2 steigen aus, wenn=
die
> Anzahl der Schlüssel größer als 50-100 wird. Dann wird die Abfrag=
e für die
> Parser dort zu komplex.

Bei IN () unterstützt Oracle bis zu 1000 Keys. Da sollte es kein Proble=
m=20
geben. DB2 ordne ich in der selben Kategorie ein.
Lass dir doch mal das SQL ausgeben und teste es auf der entsprechenden=20
Konsole (sqlplus bei Oracle).

Geht es da auch nicht? Welche Fehlermeldung?

> Jetzt könnte ich eine Tabelle füllen, indem ich obige Schleife mit =
einem
> insert versehe und dann die eigentlichen Daten mit dieser Tabelle joine=

> Leider ist sowohl hier als auch in den obigen Schleifen die Performance=
zu
> schlecht.

Über wieviele IDs reden wir denn? Schön mit Bind-Variablen und=20
Bulk-Queries gearbeitet?
Kann mir wirklich nicht vorstellen, dass der Durchlauf des Array so=20
langsam sein soll.

> Wir behelfen uns momentan damit, immer 10-20 Schlüssel zu einem SQL z=
usammen
> zu fassen und so die Anzahl der SQLs zu reduzieren.

Habt ihr mal versucht diese Queries mit UNION ALL zu verknüpfen? Sonst =

habt ihr ne Menge Netzwerklatenz mit drin...

> Das Nr-Feld in einem geschlossenen SQL zu ermitteln scheitert leider eb=
enfalls
> an der Komplexität. Die Daten gleich einzusammeln scheitert am
> Speicherverbrauch von php.

Wenn das was Produktives ist, solltest du es vielleicht a) nicht mit PHP =

machen oder b) zumindest den Speicher hochdrehen lassen.

> Das Datenmodell zu ändern ist auch so nicht möglich, Erweiterungen
> (Hilfstabellen oder sowas) sind machbar.

Kannst du mal in etwa die Datenmenge beschreiben? Und welche Operationen =

werden in PHP gemacht, die du auf der DB nicht abbilden kannst?

--=20
HTH,
Fabian

Re: Uebergabe langer Liste an Datenbank

am 22.02.2006 13:04:02 von unknown

Post removed (X-No-Archive: yes)

Re: Uebergabe langer Liste an Datenbank

am 22.02.2006 14:40:59 von unknown

Post removed (X-No-Archive: yes)

Re: Uebergabe langer Liste an Datenbank

am 22.02.2006 19:16:51 von Matthias Esken

On Wed, 22 Feb 2006 12:04:02 +0000 (UTC), Rainer Gauweiler wrote:

>> Also auch keine Möglichkeit eine VIEW oder SUBSELECT zu nutzten?
>
> Nein, leider.

Und wenn man es komplett über die Datenbank löst und die Liste der
Primärschlüssel in eine temporäre Tabelle schreibt?

SELECT daten FROM tabelle WHERE id IN (SELECT pk FROM temptable)

Gruß,
Matthias

Re: Uebergabe langer Liste an Datenbank

am 22.02.2006 19:45:34 von unknown

Post removed (X-No-Archive: yes)

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 08:46:15 von Fabian Schladitz

Rainer Gauweiler schrieb:
> On Wed, 22 Feb 2006 10:54:51 +0100, Fabian Schladitz =
wrote:
>=20
>>Rainer Gauweiler schrieb:
>>
>>>ich habe ein Array, das eine lange Liste mit Primärschlüsseln enth=
ält. Nun
>>>brauche ich die Daten, die zu diesen Schlüsseln gehören.
>>
>>Die Auswahl der Elemente geschieht im PHP?
>=20
>=20
> Ja, auch. Allerdings ebenfalls die Aggregation z.B. via Rekursion als a=
uch die
> Übernahme aus anderen Quellen (Replikation).

Okay... bei Rekursion stinkt SQL ab. Vielleicht könnte man es im PL/SQL=
=20
tun, aber da müsste man dein Problem genauer analysieren. Vom=20
Kosten/Nutzenfaktor wird dir eine PHP-Lösung vermutlich mehr helfen.

>>Schön mit Bind-Variablen und=20
>>Bulk-Queries gearbeitet?
>=20
>=20
> Bind ja. Der Begriff "Bulk-Queries" sagt mir und google so konkret nich=
ts.
> -v bitte :-)

Es gibt in einigen DB-APIs die Möglichkeit, eine Prepared Statement=20
(üblicherweise UPDATE oder INSERT) mit einer Liste von Werten übers N=
etz=20
zu schicken. Die Datenbank nimmt dann das PS und startet es nacheinander =

mit den unterschiedlichen Werten der Liste. Sehr effizient, was die=20
Netzlast angeht.

In PHP scheint es solche Sachen nicht zu geben und es ist wohl auch mit=20
deiner Forderung nach DB-Unabhängigkeit nicht zu vereinbaren.
Letztlich wirst du dich aber zwischen Performance und DB-Unabhängigkeit=
=20
entscheiden müssen. Viele Sachen sind nun Mal nur im "IBM" oder=20
"Oracle"-Flavour wirklich performant.

Siehe z.B. "executemany" von Python=20
(http://www.python.org/peps/pep-0249.html).

>>Habt ihr mal versucht diese Queries mit UNION ALL zu verknüpfen? Sons=
t=20
>>habt ihr ne Menge Netzwerklatenz mit drin...
>=20
> Nein, auf die Idee, union zu nehmen kam ich noch nicht. Und dass das Pr=
oblem
> hauptsächlich in der Netzwerklatenz liegt ist mir klar. Deswegen such=
e ich=20
> ja einen Weg das nicht in einer Schleife zu machen...

Also das würde ich noch versuchen um dein SELECT oder dein INSERT zu=20
bekommen. UNIONs insbesondere aber UNION ALL werden üblicherweise=20
separat geparst, was die Komplexität gering hält. Durch das ALL spart=
=20
sich die DB auch das lästige Sortieren.
Sinnvollerweise machst du vorher deine temporäre Tabelle leer um die=20
Performance zu steigern. Bei Oracle geht auch noch ein append-Hint.

>>Wenn das was Produktives ist, solltest du es vielleicht a) nicht mit PH=
P=20
>>machen oder b) zumindest den Speicher hochdrehen lassen.
>=20
> b) meint den physischen Speicher und nicht die Einstellung aus der
> php.ini. Lade ich die komplette Liste in den Speicher so liegt der Verb=
rauch
> bei ca 500M. Da die Kiste 10-20 concurrent User zu bewältigen hat geh=
t der=20
> Speicher aus.
> Die Web-Application-Server sollten mit 2G auskommen.

Verstehe. Aber sind die komplexen Abfragen wirklich LIVE nötig?=20
Vielleicht macht es auch Sinn, die Liste der PKs in einem bestimmten=20
Zeitintervall zu aktualisieren.
Dann noch eine materialized view auf das Ergebnis und die Performance=20
sollte stimmen.

Der Zeitintervall hängt selbstverständlich von deiner Anwendung ab.

--=20
HTH,
Fabian

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 10:42:19 von Helmut Schmuckermair

> Dummerweise hilft mir das nicht, da ich die PKs bereits in php habe. Ich
> müsste also die PKs als Block in die temp-Table bringen. Und damit wären
> wir wieder bei meiner Ursprungsfrage: Wie übergebe ich elegant und effektiv
> eine lange Liste an die Datenbank?

Ist Dir das zu langsam oder funktioniert es nur mit MySQL?

INSERT INTO test (id, name) VALUES (1, 'name1'), (2, 'name2');

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 11:06:34 von Hartmut Holzgraefe

Helmut Schmuckermair wrote:

> Ist Dir das zu langsam oder funktioniert es nur mit MySQL?
>=20
> INSERT INTO test (id, name) VALUES (1, 'name1'), (2, 'name2');

das ist zwar ANSI Syntax, aber nur optional und ich kenne bisher
außer MySQL keine DB die diese Form unterstützt

--=20
Hartmut Holzgraefe, Senior Support Engineer .
MySQL AB, www.mysql.com

http://www.mysql.com/support/

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 11:07:34 von unknown

Post removed (X-No-Archive: yes)

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 11:22:23 von external.tobias.schuetz

> Hallo zusammen,

[...]

>Gruss
> Rainer

Hallo Rainer,

nur mal so als Frage zwischendurch...gibt es für dich die Möglichkeit auf
dem DB-Server temporär ne Datei abzuspeichern?
Da ja (wie aus den anderen Posts hervorgeht) dein größtes Problem in der
Netzwerklatenz liegt, wäre es doch eine theoretische Möglichkeit, die
jeweiligen SQL-Kommandos via php in eine sql-Datei zu schreiben, die übers
Netz zu verschieben und dann direkt die Datenbank-Engine darauf los zu
lassen....

Natürlich ist die Lösung ein wenig durch die Brust ins Auge, aber unter den
gegebenen Umständen vielleicht noch die praktikabelste.

Ob du dann eine temporäre Tabelle aus deinen Schlüsseln aufbaust oder
sonstwas damit machst ist ja dann schlußendlich von php unabhängig und du
mußt nur sorge tragen, dass du den Moment wenn die DBEngine fertig ist,
wieder triffst...

Gruß
Tobias

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 11:30:01 von Axel Schwenke

Rainer Gauweiler wrote:
> On Wed, 22 Feb 2006 19:16:51 +0100, Matthias Esken wrote:
>>
>> SELECT daten FROM tabelle WHERE id IN (SELECT pk FROM temptable)
>
> Hm, ich würde eher
> select daten from tabelle inner join temptable on (tabelle.pk = temptable.pk)
> bevorzugen. Ich tippe mal, dass auch bei einem select im in-Operater die Anzahl
> begrenzt ist, bei einem Join ist sie das nicht.
>
> Dummerweise hilft mir das nicht, da ich die PKs bereits in php habe. Ich
> müsste also die PKs als Block in die temp-Table bringen. Und damit wären
> wir wieder bei meiner Ursprungsfrage: Wie übergebe ich elegant und effektiv
> eine lange Liste an die Datenbank?

Üblicherweise bietet ein Datenbank-API Array-Modi für bestimmte
Operatioen an. Typisch wäre Array-Insert für das Laden großer
Datenmengen. Aber ob das dann auch im PHP-API implementiert ist?

MySQL kennt z.B. die erweiterte INSERT-Syntax mit mehreren Werte-
listen: INSERT ... VALUES (...), (...), ...

Sonst baut man halt eine Schleife mit Prepare, Bind, Execute.
Allerdings sind die nativen Datenbank-APIs in MySQL jeweils sehr
unterschiedlich. Und die generischen APIs beherrschen solche
Spezialitäten meist gar nicht erst.


XL

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 12:02:16 von unknown

Post removed (X-No-Archive: yes)

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 13:08:33 von unknown

Post removed (X-No-Archive: yes)

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 13:37:34 von external.tobias.schuetz

> Hallo zusammen,
>
> On Thu, 23 Feb 2006 11:22:23 +0100, Tobias Schütz wrote:
>
> Naja, es ist nicht nur die *Netzwerk*latenz sondern natürlich auch der
> allgemeine Overhead einer SQL-Anweisung 10000 SQLs sind einfach langsamer
> als ein SQL mit 10000 Werten.

Jo, allerdings (das war jedenfalls ein Fazit, was ich aus den anderen Posts
gezogen habe) kommst du nicht darum herum einen kleinen Tod in irgendeiner
Richtung zu sterben.
Wenn du Verallgemeinerung auf ein beliebiges DBMS willst, dann mußt du auch
damit leben die max. Zahlen der Schlüssel pro Query zu beschränken und dann
von DBMS zu DBMS diese Anzupassen.... oder eben mit einzelnen Querys
arbeiten, die dann natürlich den Overhead mit sich führen...

> An deinen Vorschlag dachte ich auch schon. Ich habe sogar schon daran
gedacht
> über direkte TCP-Verbindungen was reinzuholen. Aber das ist alles extrem
> aufwändig, da es ja dann auch für mehrere DBMs funktionieren muss und ich
> ja eigentlich "nur" eine feldweise Verarbeitung bräuchte.

Aufwendig ist es ohne Frage... wobei über die direkte TCP Verbindung das
ganze noch kompilizerter wird als "nur" ein File durch das Ethernet zu
bewegen, bzw. auf eine Freigabe zuzugreifen...

> Das Timing ist da sicherlich eine Sache, Locking und 15 andere User die
darauf
> warten dass die Tabelle wieder frei wird eine andere - alles nicht so
rechte
> Regionen die ich angreifen will.

Hm, kann ich gut verstehen, aber dafür wäre dann deine temporäre Tabelle in
die du die Schlüssel einträgst (um se hinterher über einen Join zu
verknüpfen) sicher eine gute Methode um das Locking so gering wie möglich zu
halten.

Vielleicht wäre es auch gar keine so schlechte Idee zumindest eine Statistik
mitlaufen zu lassen, welche Kombinationen (bzw. Unterkombinationen) in
deinen Schlüsseln am Häufigsten gebraucht werden und diese schon
vorgefertigt in die DB abzulegen...dann würdest du einfach hinterher
Kombinationen zusammenschalten und unnötiges eventuell rauswerfen...

> Gruss
> Rainer

Gruß
Tobias

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 13:58:44 von unknown

Post removed (X-No-Archive: yes)

Re: Uebergabe langer Liste an Datenbank

am 23.02.2006 21:34:30 von Matthias Esken

On Thu, 23 Feb 2006 11:02:16 +0000 (UTC), Rainer Gauweiler wrote:

>>> INSERT INTO test (id, name) VALUES (1, 'name1'), (2, 'name2');
>
>> das ist zwar ANSI Syntax, aber nur optional und ich kenne bisher
>> außer MySQL keine DB die diese Form unterstützt
>
> db2 macht es mit, oracle und mssql nicht.
>
> Kennt jemand für letztere zwei eine alternative Syntax die sowas bewirkt?

Das nicht, aber mir fallen immer schäbigere Varianten ein. Man könnte unter
Oracle die IDs in ein File schreiben und das Ding dann als External Table
einbinden.

Gruß,
Matthias

Re: Uebergabe langer Liste an Datenbank

am 24.02.2006 08:41:34 von unknown

Post removed (X-No-Archive: yes)