Schrift
[thread]10152[/thread]

Welche Variante von fetch* mit DBI benutzen?

Leser: 1


<< >> 10 Einträge, 1 Seite
Gast Gast
 2007-08-20 23:27
#98446 #98446
Hallo!

Ich habe bisher in nahezu allen meinen Scripten fetchrow_array() verwendete um per DBI an meine SQL Daten zu kommen.

Welche Variante empfehlt Ihr?
Gibt es Unterschiede in der Performance zwischen zum Beispiel fetchrow_array() und fetch() oder fetchrow_hashref()?

Im Moment schiene mir rein aus programmiertechnischer Sicht die hashref Variante am bequemsten...

Bitte um Erleuchtung!

mfg
christian reiter
c (dot) reiter ( a ) gmx (dot) net
pq
 2007-08-20 23:42
#98449 #98449
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
fetchrow_hashref ist etwas langsamer als fetchrow_arrayref, aber es kommt ganz
auf dein programm an, ob dir der unterschied zu gross ist oder nicht.
mit CPAN:Benchmark kannst du es ja mal testen.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Gast Gast
 2007-08-20 23:56
#98451 #98451
Ist dann die Variante fetchrow_array() am langsamsten?
Klingt als würden hier erst mal alle Zeilen in ein Array kopiert...

mfg
christian
pq
 2007-08-21 00:00
#98452 #98452
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
das kann man so pauschal nicht sagen, teste es bitte aus.
letztendlich kommt es ja auch darauf an, was du hinterer mit den arrays/arrayrefs/hashes
machst.
und ich weiss ja nicht, was du da für ein programm hast und wieviele user,
aber ich vermute mal, in deinem fall macht es kaum einen unterschied.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Gast Gast
 2007-08-21 00:07
#98453 #98453
pq+2007-08-20 22:00:03--
aber ich vermute mal, in deinem fall macht es kaum einen unterschied.


Davon kann man ausgehen. Meist handelt es sich um Webapplikationen mit sehr beschränktem Benutzeraufkommen. Die Daten werden zu 80% direkt in HTML Tabellen ausgegeben.

Meine Frage zielte eher darauf ab, in Zukunft möglichst "sauberen Code" zu produzieren.

Auf alle Fälle, vielen Dank für deine Ausführungen.

mfg
christian
Strat
 2007-08-26 14:43
#98687 #98687
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
Zur Geschwindigkeit: das schnellste ist meist, wenn man mit BindColumns arbeitet (siehe perldoc DBI).

zu den verschiedenen Fetchrow's:
Wenn im SELECT ein * vorkommt, halte ich fetchrow und fetchrow_arrayref fuer zu unsicher, weil sich unter Umstaenden die Reihenfolge der zurueckgelieferten felder aendern kann, und das script dann vermutlich nur noch Murks baut. Also verwende ich da eigentlich immer fetchrow_hashref.

Wenn man mit einem Templating System und SQL pur arbeitet (also keiner Abstraktionsschicht wie DBIx oder aehnlichem), ist meist fetchrow_hashref am komfortabelsten, weil man im SQL schon die Namen der Zielfelder angeben kann:
[sql]
SELECT name AS nick, timestamp as LastPostDate FROM table
[/sql]
und den zurueckerhaltenen Hash einfach in die entsprechende Struktur transformieren kann.
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
sid burn
 2007-08-26 15:38
#98689 #98689
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Zu der Performance.

Ich habe es nicht getestet, allerdiengs habe ich diese Infos aus "Prgrammieren mit Perl DBI" was ja immerhin auch vom DBI entwickler ist. Dort sagt er kurz und knapp folgende drei Sachen: (Ungefähr Sinngemäß wiedergegeben)

fetchrow_array = Langsam, wenn die Werte ausgelesen werden müssen, müssen sie später immer wieder in das neue Array kopiert werden.

fetchrow_arrayref = Deutlich schneller, da die Werte nur einmal ausgelesen werden, und dann einfach eine Referenz zurück gegeben wird.

fetchrow_hashref = Ist auch wieder langsam, da es intern relativ komplex sein soll die Tabellennamen auszulesen die für die Keys benötigt wird. Ob es jetzt langsamer als ein fetchrow_array ist weiß ich nicht, ich vermute ja. Ansonsten hat fetchrow_hashref aber noch paar mehr Nachteile. Wenn du beim Paramter eine Berechnung machst hast du relativ blöde Key namen, umgehen kannst du es dann mit einer Zuweisung der berechnung in einem leserlichen Namen im SQL. Identische Attributenamen aus unterschiedlichen Tabellen können ebenfalls Probleme hervorrufen. Ansonsten waren da glaube ich noch ein paar Sachen. Habe mir jedenfalls im großen und ganzen einfach nur gemerkt fetchrow_hashref() nicht zu nutzen. Auch wenn es sicherlich bequem ist.


Am schnellsten und das was am wenigsten Probleme bereit ist also fetchrow_arrayref. wenn du ein "SELECT *" machst kann dies natürlich wieder anders aussehen. Aber man sollte soetwas erst nie machen. Selbst wenn du alle Werte haben möchtest solltest du die werte einzelnt auflisten.

Noch schneller ist natürlich bind_column da du ihn die Referenzen vor dem auslesen schon mitgibst. Du sparst dir also das Kopieren einer Referenz bei fetchrow_arrayref. Allerdiengs kostet das kopieren einer Referenz nicht wirklich viel. Ist also kein großer Verlust. Vergleichen zur bind_column Variante ist dann Meiner Meinung nach die fetchrow_arrayref varinte lesbarer, und besser aufgebaut. Ich finde bind_column Variante nicht so toll, und es zerstreut meiner Meinung nach auslesen und setzen der Variablen im Sourcecode.


Ansonsten wenn du Performance Probleme hast, dann solltest du einen Profiler nutzen und erstmal die Schwachstellen identifizieren bevor du änderungen machst, die gar nicht ausschlaggebend sind.
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
ptk
 2007-08-26 21:25
#98696 #98696
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
sid burn+2007-08-26 13:38:57--
Am schnellsten und das was am wenigsten Probleme bereit ist also fetchrow_arrayref. wenn du ein "SELECT *" machst kann dies natürlich wieder anders aussehen. Aber man sollte soetwas erst nie machen. Selbst wenn du alle Werte haben möchtest solltest du die werte einzelnt auflisten.

Warum? Insbesondere, wenn man es im Zusammenhang mit fetchrow_hashref verwendet und somit die Spaltenreihenfolge keine Rolle spielt?
Strat
 2007-08-27 10:46
#98705 #98705
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
sid burn+2007-08-26 13:38:57--
Ansonsten hat fetchrow_hashref aber noch paar mehr Nachteile. Wenn du beim Paramter eine Berechnung machst hast du relativ blöde Key namen, umgehen kannst du es dann mit einer Zuweisung der berechnung in einem leserlichen Namen im SQL. Identische Attributenamen aus unterschiedlichen Tabellen können ebenfalls Probleme hervorrufen.


Zu bloede Key namen: dafuer gibt's ja AS, z.B.
[sql]
SELECT count(id) AS anzahl FROM $table
[/sql]
dies hat ueberdies den Vorteil, dass man die Gross-/Kleinschreibung der Keys im Script bestimmen kann und sich nicht auf das, was in der DB vorkommt, verlassen muss, gerade wenn die Datenbank nicht von einem selbst stammt.

Sowas aehnliches kann (bzw. sollte) man auch bei mehreren identischen Feldnamen machen:
[sql]
SELECT USER.id AS uid, MSG.id AS msgId, USER.nick AS nick
FROM user AS USER, messages AS MSG
WHERE USER.id = MSG.authorId
[/sql]
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
sid burn
 2007-08-27 19:23
#98720 #98720
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Zu bloede Key namen: dafuer gibt's ja AS

Ja, das meinte ich mit
Quote
umgehen kannst du es dann mit einer Zuweisung der berechnung in einem leserlichen Namen im SQL.
vielleicht hätte ich es anders schreiben sollen.

Quote
dies hat ueberdies den Vorteil, dass man die Gross-/Kleinschreibung der Keys im Script bestimmen kann und sich nicht auf das, was in der DB vorkommt, verlassen muss, gerade wenn die Datenbank nicht von einem selbst stammt.

Das ergibt so wie du es schreibst für mich keine logik. Nach dieser logik kann man also auch kein "SELECT *" nutzen da man ja für alles mit "as" einen neuen Namen setzen muss, da die groß/kleinschreibung ja anders sein könnte. Damit hätte ich keinen Vorteil, und das SQL wird sogar noch länger als bei einem fetchrow_arrayref() den da kann ich mir die "AS ..." sparen.

Aber so nebenbei gesagt, du kannst folgendes machen.
Code (perl): (dl )
$hash_ref = $sth->fetchrow_hashref('NAME_lc');

Dann werden alle Keys automatisch in kleinbuchstaben umgewandelt.

Du kannst das Attribut aber auch auf dem Datenbank handle setzen, so musst du das nicht bei jeder Abfrage neu setzen.

Code (perl): (dl )
$dbh->{FetchHashKeyName} = 'NAME_lc';



----


Aber insgesamt wie du es schreibst sehe ich keine Vorteile mehr. Bei identischen Hash Keys musst du sowieso wieder manuel mit "AS" direkte Namen zuweisen. Zudem ist ein fetchrow_hashref langsamer als ein normalen fetchrow_array() und vorallem als ein fetchrow_arrayref()

Zitat aus perldoc DBI:
Quote
Because of the extra work "fetchrow_hashref" and Perl have to perform, it is not as efficient as "fetchrow_arrayref" or "fetchrow_array".


Es kann genau in dem Sonderfall nützlich sein wenn man ein "SELECT *" macht, wenn man alles oben beachtet. Ich finde das zu komplex.

Ein fetchrow_arrayref() ist performant und man muss da nicht so viele sonderfälle beachten. Ich meine aber immer noch das da noch etwas war was gegen fetchrow_hashref() spricht, ich weiß aber nicht mehr genau was es war.
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
<< >> 10 Einträge, 1 Seite



View all threads created 2007-08-20 23:27.