Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 19 von 19

Thema: Ergebnismenge in Variable packen

  1. #11
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von kiaaap Beitrag anzeigen
    Hallo noch mal,

    leider war meine Freude etwas verfrüht.
    Keine Fehlermeldungen zu bekommen ist leider nicht immer mit 'funktioniert auch' gleich zu setzen.

    Die als VARCHAR deklarierte Variable 'keys_a' übernimmt zwar die Ergebnismenge der Funktion 'hmGetMatchKeys( ... )' (Rückgabewert: RETURNS SETOF character varying), scheint sich aber nur den ersten Wert zu "merken" ... daher werden meine Schleifen folglich auch nur ein mal durchlaufen.
    Klingt so, als ob Du "return next;" vergessen hast.

    (Die Informix-Version mit Variablen als Zwischenspeicher läuft 25x schneller)
    Niemand zwingt Dich zu iregdnwas, oder?
    [/quote]

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  2. #12
    fristo ist offline Super-Moderator
    Registriert seit
    08.12.2005
    Ort
    Raum Frankfurt/Main
    Beiträge
    668

    Standard

    Hallo Andreas (kiaaap),

    Zitat Zitat von kiaaap Beitrag anzeigen
    Die als VARCHAR deklarierte Variable 'keys_a' übernimmt zwar die Ergebnismenge der Funktion 'hmGetMatchKeys( ... )' (Rückgabewert: RETURNS SETOF character varying), scheint sich aber nur den ersten Wert zu "merken" ... daher werden meine Schleifen folglich auch nur ein mal durchlaufen.
    RETURNS SETOF ... liefert 0...n Zeilen einer Abfrage zurück. Die Variable 'keys_a' kann in der definierten Form nur 1 Zeile speichern. Mehrere Zeilen kann man nur in Tabellen speichern!



    mfg

    fristo

  3. #13
    kiaaap ist offline Benutzer
    Registriert seit
    08.05.2007
    Ort
    Ulm
    Beiträge
    31

    Standard

    Natürlich zwingt mich keiner zu irgend was, der Faktor 25 sollte auch nur den Performanceverlust durch die Tabellen statt Variablen verdeutlichen.

    Allerdings würde es mich als Freund von Open Source - Produkten doch schon freuen, wenn diese im Vergleich zu kommerziellen Produkten gut da stehen

    Hintergrund: Ich mache gerade ein studentisches Praktikum und meine Aufgabe ist ein Performance-Vergleich Informix vs. Postgres bzgl. der hier benötigten Datenbankanforderungen. Bisher steht Postgres v.a. in Bezug auf die Performance ausgesprochen gut da ... daher verwundert bzw. stört mich dieses Problem doch ein wenig.

    Zurück zum Problem:
    Also die Funktion selbst ist ja in C geschrieben und liefert ordnungsgemäß die gewünschte Tabelle zurück. Wenn ich die Tabellen (hier t_temp_keys_a u.s.w.) zum zwischenspeichern verwende funktioniert ja auch alles.
    Nur wenn ich die Variablen (keys_a, u.s.w.) verwende bekommt die FOR-Schleife nur einen Wert. Daher meine Vermutung das ich bei der Zuweisung der Funktionsrückgabe in die Variable bzw. in der FOR-Schleife einen Fehler habe ... auch wenn PG nichts anzeigt.

    Code:
    ...
    /*
    INSERT INTO t_temp_keys_a  VALUES (hmGetMatchKeys(  'A',  a1,  a2,    'A*', dna_a1, dna_a2, pop_id, threshold ));
    INSERT INTO t_temp_keys_b  VALUES (hmGetMatchKeys(  'B',  b1,  b2,    'B*', dna_b1, dna_b2, pop_id, threshold ));
    INSERT INTO t_temp_keys_dr VALUES (hmGetMatchKeys( 'DR', dr1, dr2, 'DRB1*',  drb11,  drb12, pop_id, threshold ));
    */
    
    SELECT hmGetMatchKeys(  'A',  a1,  a2,    'A*', dna_a1, dna_a2, pop_id, threshold ) INTO keys_a;
    SELECT hmGetMatchKeys(  'B',  b1,  b2,    'B*', dna_b1, dna_b2, pop_id, threshold ) INTO keys_b;
    SELECT hmGetMatchKeys( 'DR', dr1, dr2, 'DRB1*',  drb11,  drb12, pop_id, threshold ) INTO keys_dr;
    
    FOR cur_a IN SELECT keys_a LOOP
       FOR cur_b IN SELECT keys_b LOOP
          cnt := 0;
          FOR cur_dr IN SELECT keys_dr LOOP
             ...

  4. #14
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von fristo Beitrag anzeigen
    Hallo Andreas (kiaaap),

    RETURNS SETOF ... liefert 0...n Zeilen einer Abfrage zurück. Die Variable 'keys_a' kann in der definierten Form nur 1 Zeile speichern. Mehrere Zeilen kann man nur in Tabellen speichern!

    mfg

    fristo
    Nein. Schau:

    Code:
    test=# select * from foo;
     id |   word
    ----+-----------
      1 | car
      1 | fruit
      2 | car
      2 | fruit
      3 | car
      3 | vegetable
      2 | vegetable
      1 | car
    (8 rows)
    
    Time: 0.779 ms
    test=*# create function get_all() returns setof text as $$declare t record;begin for t in select word from foo loop return next t.word; end loop; end;$$language plpgsql;
    CREATE FUNCTION
    Time: 1.883 ms
    test=*# select * from get_all();
      get_all
    -----------
     car
     fruit
     car
     fruit
     car
     vegetable
     vegetable
     car
    (8 rows)
    t ist eine RECORD-Variable, sie speichert keine Tabelle, sondern 'nur' eine Zeile.

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  5. #15
    kiaaap ist offline Benutzer
    Registriert seit
    08.05.2007
    Ort
    Ulm
    Beiträge
    31

    Standard

    Ich fürchte ich drücke mich falsch oder undeutlich aus ... oder ich blicke es einfach nicht ( was wohl eher zutrifft ).

    Mit SELECT * FROM hmGetMatchKeys( ... Parameter ...); bekomme ich auch meine gewünschte Tabelle zurück, wie in Deinem Beispiel.

    Genau diesen Inhalt möchte ich aber in meiner zweiten Funktion für die verschachtelten FOR-Schleifen nutzen und zwar ohne jedesmal wieder die Funktion hmGetMatchKeys( ... Parameter ...) aufrufen zu müssen.

    Daher Suche ich einen Weg die mit der Funktion ermittelte Grundgesamtheit durch die meine Schleifen iterieren sollen,so zwischen zu speichern, das die geschachtelten Schleifen öfter darauf zugreifen können.

    Ich brauche also irgend was im Sinne von:
    Code:
    FOR cur_a IN variable_mit_tabelle LOOP
    Sorry für die Mühe ... und vielen Dank für die Geduld ...

  6. #16
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von kiaaap Beitrag anzeigen
    Ich fürchte ich drücke mich falsch oder undeutlich aus ... oder ich blicke es einfach nicht ( was wohl eher zutrifft ).
    keine Ahnung...


    Daher Suche ich einen Weg die mit der Funktion ermittelte Grundgesamtheit durch die meine Schleifen iterieren sollen,so zwischen zu speichern, das die geschachtelten Schleifen öfter darauf zugreifen können.
    Eine SRF (Set Returning Function) liefert Dir quasi eine Tabelle. Mit der kannst Du wieder wie mit einer 'normalen' Tabelle arbeiten. Ausgehend von meinem Beispiel:

    Code:
    test=*# select upper(foo) from get_all() foo;
       upper
    -----------
     CAR
     FRUIT
     CAR
     FRUIT
     CAR
     VEGETABLE
     VEGETABLE
     CAR
    (8 rows)
    Hilft das?

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  7. #17
    kiaaap ist offline Benutzer
    Registriert seit
    08.05.2007
    Ort
    Ulm
    Beiträge
    31

    Standard

    Hallo Andreas,

    super Idee ... so wie ich das verstehe löst das aber leider nicht mein Problem.

    Ich führe den gravierenden Performance-Unterschied auf das entstehende Skalar in Bezug auf die Funktionsaufrufe zurück.

    Nehmen wir an das jede Function eine Tabelle mit nur 10 Relationen zurückgibt:
    Code:
    FOR a IN SELECT * FROM function_a() LOOP           <--- 1x
                                                                                      |
       FOR b in SELECT * FROM function_b() LOOP         <--- 10x
                                                                                      |
          FOR c IN SELECT * FROM function_c() LOOP     <--- 100x
    
             ...
    
          END LOOP;
    
       END LOOP;
    
    END LOOP;
    In diesem Beispiel wären zum Abarbeiten aller schleifen also insgesamt 111 Funktionsaufrufe notwendig. Wenn ich das Ergebnis der drei Funktionen in Variablen halten könnte (so wie es bei Informix implementiert wurde) sind es halt nur 3 Funktionsaufrufe.

    Ich werde als nächstes mal den CREATE FUNCTION - Statements der drei Funktionen mal ein 'IMMUTABLE' spendieren ... in der Hoffnung, da noch etwas Zeit einzusparen. (Hätte ich eigentlich auch schon früher machen können...)

    Interessehalber lasse ich die ganze Sache mal mit den Attributen IMMUTABLE | STABLE und VOLATILE laufen, um den Performance-Unterschied zu messen.

    Und wenn alles nichts hilft, werde ich mal versuchen die Funktion mit den Schleifen in Perl zu implementieren ... da kann man ja Tabellen in Variablen packen.

    Viele Grüße,

    Andreas

  8. #18
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    [QUOTE=kiaaap;7575]Hallo Andreas,

    super Idee ... so wie ich das verstehe löst das aber leider nicht mein Problem.

    Ich führe den gravierenden Performance-Unterschied auf das entstehende Skalar in Bezug auf die Funktionsaufrufe zurück.


    In diesem Beispiel wären zum Abarbeiten aller schleifen also insgesamt 111 Funktionsaufrufe notwendig. Wenn ich das Ergebnis der drei Funktionen in Variablen halten könnte (so wie es bei Informix implementiert wurde) sind es halt nur 3 Funktionsaufrufe.
    [code]
    Dann erzeuge Arrays aus dem Resultat, also sowas wie:
    Code:
    test=# CREATE AGGREGATE array_accum (
    test(#     sfunc = array_append,
    test(#     basetype = anyelement,
    test(#     stype = anyarray,
    test(#     initcond = '{}'
    test(# );
    CREATE AGGREGATE
    test=*# commit;
    COMMIT
    test=# select * from foo;
     id |  t
    ----+-----
      5 | 1,2
      6 | 2,2
      7 | 3,2
      1 | 1
      1 | 1
    (5 rows)
    
    test=*# select array_accum(id), array_accum(t) from foo;
     array_accum |       array_accum
    -------------+-------------------------
     {5,6,7,1,1} | {"1,2","2,2","3,2",1,1}
    (1 row)
    In Deiner Funktion rufst Du dann halt nur einmalig die SRF auf und kippst das in Arrays, die Du dann mit den Arrayfunktionen durchlaufen kannst.

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  9. #19
    kiaaap ist offline Benutzer
    Registriert seit
    08.05.2007
    Ort
    Ulm
    Beiträge
    31

    Standard

    Hallo Andreas,

    ich habe inzwischen meine Funktion mit den FOR-Schleifen nochmal in Perl geschrieben, denn eine externe Bibliothek auf die ich in jedem Durchgang zugreifen muss basiert auch auf Perl ... da bot es sich einfach an diesen Weg zu gehen. Ich habe allerdings Deinen letzten Vorschlag mit in unsere Doku aufgenommen, um diese Vorgehensweise bei anderen Matching-Schleifen zu nutzen.

    Perl-Version:
    Code:
       my $keys_a  = hmGetMatchKeys( "A", $a1,  $a2,
                                     "A*", $dna_a1, $dna_a2, $pop_id, $threshold );
    
       my $keys_b  = hmGetMatchKeys( "B", $b1,  $b2,
                                     "B*", $dna_b1, $dna_b2, $pop_id, $threshold );
    
       my $keys_dr = hmGetMatchKeys( "DR", $dr1, $dr2,
                                     "DRB1*", $drb11, $drb12, $pop_id, $threshold );
    
       foreach my $key_a ( @$keys_a ) {
          foreach my $key_b ( @$keys_b ) {
             foreach my $key_dr ( @$keys_dr ) {
    Die Performance ist nun auch schon viel erfreulicher. Aus Faktor 25 wurde Faktor 4 .

    Vermutlich hat Informix noch die Nase vorn, weil es besagte Perl-Bibliothek nach dem ersten Aufruf permanent im Speicher hält, während Postgres vermutlich bei jedem Funktionsaufruf die Bibliothek neu lädt.

    Das ist bei Informix natürlich ganz toll für die Performance ... allerdings muss bei jedem Update der Bibliothek der Server neu gestartet werden (nicht so toll).

    Gibts da bei Postgres vielleicht einen eleganteren Weg, eine geladene Bibliothek für längere Zeit (sprich über eine Session hinaus) im Speicher zu halten ?

Seite 2 von 2 ErsteErste 12

Ähnliche Themen

  1. Variable Definieren
    Von trojannus im Forum SQL
    Antworten: 2
    Letzter Beitrag: 08.03.2012, 09:49
  2. variable für spaltennamen
    Von wuchermann im Forum Trigger und Funktionen
    Antworten: 8
    Letzter Beitrag: 14.05.2009, 15:25
  3. zufällige Zeile aus Ergebnismenge
    Von micho2 im Forum SQL
    Antworten: 3
    Letzter Beitrag: 29.10.2007, 21:16
  4. Antworten: 8
    Letzter Beitrag: 17.09.2007, 15:22
  5. SELECT_anweisung mit Variable
    Von Chuqa im Forum Trigger und Funktionen
    Antworten: 2
    Letzter Beitrag: 05.02.2007, 15:20

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Links: Tobias Bauer - IT- und Funkdienstleistungen   -   Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen   -   Funkforum