Schrift
[thread]3828[/thread]

Select Abfrage unter Perl zu langsam



<< >> 7 Einträge, 1 Seite
Gast Gast
 2007-06-29 12:18
#35555 #35555
Hallo zusammen,

ich habe schon das internet durchforstet aber irgendwie habe ich noch nix gescheites zu meinem Problem gefunden. Daher versuche ich es mal über diesen Weg.

ich habe ein Perl-Script. Mit diesem Script möchte ich Daten aus eine MySQL-Datenbank ziehen (Adressen), welche ca. 3 Mio Datensätze hat. Hierbei mach ich einen Select-befehl und möchte z.b. 2000 Datensätze ziehen.
Leider bin ich in dieser Hinsicht noch ein Newbie und daher nicht so bewandert. Das problem liegt in der Performance. So brache die Select-Anweisung viel zu lange in meinen Augen und ich habe keine Ahnung warum dies der Fall ist. Ich hoffen mir kann jemand helfen.
Hier der Code:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!    /usr/bin/perl
use DBI;
@tmp_bu=(1,2,3,4,5,6,7,8,9)
$i=0;
open(OUT,'>>',"$Pfad"."SAM"."$samzahl") or die "$!";

while (<@tmp_bu>) # je bundesland
{
     
       $zahl[$i]=2000;
       #Prüfung verfügbarer Adressen, sonst maximal mögliche verwenden
       $sql="SELECT Count(Lfd_Nr) FROM Daten WHERE Bundesland=".$tmp_bu[$i].";";
       $row = $dbh->selectrow_arrayref($sql);
       $verfugadr = $row->[0];
       if ($verfugadr < $zahl[$i]) {$zahl[$i]=$verfugadr;}

#selectrow is extrem langsam, gibts da ne andere Methode?
# -> extremer Zeitfresser


       
       $sql = "SELECT Lfd_Nr, Vorname, Name, Adresse, PLZ, Bundesland, Anz_Benutz  FROM Daten WHERE Bundesland=".$tmp_bu[$i]." ORDER BY Name asc, rand() limit ".$zahl[$i].";";}
       
       my $sth = $dbh->prepare($sql) || die DBI->errstr();
       $sth->execute() || die DBI->errstr();

#hier das execute sehr langsam. das prepare kann ich nicht außerhalb der ersten
#Schleife machen, da er das limit nicht richtig setzen kann.
#also wenn ich außerhalb das prepare mache mit "limit ?",
#dann erzeugt mir prepare und execute jeweils ein ' so dass dann stehen würde "limit ''40''
# -> extremer Zeitfresser
 
       while (@row = $sth->fetchrow_array)
       {
               $key=$key+1;
               
               $results="*key=$key;nam=$row[1] $row[2];adr=$row[3];plz=$row[4];;bland=$row[5]";
               print OUT "$results\n";
               
               $benutz=$row[6]+1;
               if ($benutz == 6) {$benutz=0;}
               my $sql = "UPDATE Daten SET Anz_Benutzung=$benutz WHERE Lfd_Nr=$row[0]";
               my $sth = $dbh->prepare($sql) || die DBI->errstr();
               $sth->execute() || die DBI->errstr();
               
#das execute ist zwar auch net schnell aber schneller als das erste :-)


       }
       $i=$i+1;
       $sth->finish;
}


Ich habe das Script mit DProf geprüft und besonders beim execute der Select Anweisung ist es extrem langsam. Für Hilfe bin i sehr dankbar.

Lg
Stefan

edit pq: code-tags hinzugefügt\n\n

<!--EDIT|pq|1183123814-->
MisterL
 2007-06-29 13:38
#35556 #35556
User since
2006-07-05
334 Artikel
BenutzerIn
[default_avatar]
Also wenn ich die Lektionen in punkto Perl und Datenbanken hier richtig verstanden habe, kann die ?-Notation die Abfragen beschleunigen. Die festen Teile der SQL-Abfrage werden zudem ausserhalb der Schleife untergebracht.
Wenn allerdings die Hardare oder das Datenmodell der Flaschenhals ist, wird das nicht gerade den Geschwindigkeitsrausch bringen

Gruss MisterL
“Perl is the only language that looks the same before and after RSA encryption.”
bloonix
 2007-06-29 13:57
#35557 #35557
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
[quote=Guest,29.06.2007, 10:18]@tmp_bu=(1,2,3,4,5,6,7,8,9)
...
while (<@tmp_bu>) # je bundesland[/quote]
Schreibt man das so?

Ausserdem hast du kein strict, kein warnings und keine Code-Tags.
So macht es keinen Spaß dir zu helfen!
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
renee
 2007-06-29 15:19
#35558 #35558
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Generell solltest Du es in dieser Art machen:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
my $sql = q~SELECT * FROM tabelle WHERE spalte = ?~;
my $sth = $dbh->prepare( $sql ) or die $dbh->errstr;

for my $var ( @array ){
    $sth->execute( $var ) or die $dbh->errstr;

    while( my @row = $sth->fetchrow_array ){
        print "@row\n";
    }
}


Also vor der Schleife schon das prepare machen und in der Schleife nur noch das execute.
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Sucher
 2007-06-29 16:14
#35559 #35559
User since
2007-03-26
47 Artikel
BenutzerIn
[default_avatar]
Hallo,

hast du deine Statements mal von einem anderen Client aus laufen lassen? Select Count z.B., wäre auf Pg eine lange Abfrage. Vielleicht ist das bei MySQL anders...
Ich sehe aber auch gar nicht die Notwendigkeit dafür. Du kannst doch in jedem Fall 'LIMIT 2000' sagen. Dann fetchst du die Zeilen, schaust, wie viele es waren und holst ggf. die nächsten 2000.
Hat Bundesland einen Index?

Grüße,
pq
 2007-06-29 17:29
#35560 #35560
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
[quote=opi,29.06.2007, 11:57][quote=Guest,29.06.2007, 10:18]
while (<@tmp_bu>) # je bundesland[/quote]
Schreibt man das so?[/quote]
nein. es funktioniert nur zufällig.
aber ich staune auch immer wieder, warum so viele nicht einfach über
das array mit foreach iterieren und stattdessen die glob-funktion drauf
loslassen und mit while drüber iterieren.
das muss in irgendeinem buch stehen.
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
nepos
 2007-06-29 17:38
#35561 #35561
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
@Sucher: Soweit ich weiß hat MySQL, zumindest, wenn man mit MyISAM-Tabellen arbeitet, die Anzahl der Zeilen intern gespeichert. Drum ist der oft gemacht Vergleich von
Code: (dl )
SELECT COUNT(*) FROM bla
zwischen MySQL und Postgres absolut Käse, da PosgreSQL dafür wirklich einen sequentiellen Tablescan machen muss.
<< >> 7 Einträge, 1 Seite



View all threads created 2007-06-29 12:18.