Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]3653[/thread]

Was kann sql vertragen?



<< |< 1 2 3 >| >> 21 Einträge, 3 Seiten
olruebe01
 2006-01-19 23:17
#33917 #33917
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
Hallo,

ich habe eine Problematik, bzw. eine Frage.

Ich habe einen Bilderdienst, bei dem Bilder auf meinem Server gespeichert und dann per <IMG TAG> bei eBay eingebunden werden. Der Aufruf der Bilder erfolgt hierbei über ein Script, dass überprüft, ob das Bild angezeigt werden darf oder nicht und ggf. sonst ein Fehlerbild ausgibt.

Ich mache das bisher über Perl. Die Auktionsnummer wird hierbau aus dem Refferer gelsen.

Code: (dl )
1
2
 
if (!-e "blacklist/$auktionsnummer.dat") {print "location: bildpfad.jpg"} else {print "locationFehlerbild.jpg"}


Das funzt auch. Nun ist mein Server ziemlich an der Belastungsgrenze und man hat mir geraten, mich mal mit SQL zu beschäftigen. Nun habe ich als erstes mal alle Auktionsnummern der gesperrten Auktionen in eine SQL DB geschrieben. Zum Test sind nur ca. 350 Einträge drin.

Nun wird bei jedem Aufruf eines Bildes in der DB nachgesehen, ob die Auktionsnummer eingetragen ist. Wenn ja -> Fehlerbild, sonst korrektes Bild.
Auch das funktioniert, wenn ich es selber teste. Wenn ich das Script aber richtig in den Dienst stelle, legt es meinen Server lahm und es geht nichts mehr. load average steigt auf über 150, FTP kaum noch möglich, etc...

Mein Gedanke nun: Kann es sein, dass sql zu langsam ist? Ist vielleicht meine vorherige Idee bie Bessere?

Es sind ständig so um die 15.000 Auktionen aktiv, die jeweils zwischen 3 und 12 Fotos von mir integriert haben. Und: Bei nur EINEM Aufruf einer Auktion mit 12 Bildern, folgt ja auch 12 mal die Abfrage - für jedes Bild eben. Allerdings ist dies auch bei der anderen Version der Fall. JEDES aufgerufene Bild erzeugt die Abfrage, ob es angezeigt werden darf oder nicht.

Über sql mache ich das so?

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/perl -w

use CGI::Carp qw(fatalsToBrowser);
# Dateiflock
use Fcntl qw(:DEFAULT :flock);
use CGI qw(:standard);
use CGI;


use DBI;
my $datenbank = "blacklist";
my $datenbankhost = "localhost";
my $datenbankuser = "xxxebe";
my $datenbankpw = "xxxxte";


######  Übergebene Werte efassen
if ($ENV{'REQUEST_METHOD'} eq 'GET')
{
       $querystring = $ENV{'QUERY_STRING'};}

@arrnameval = split(/&/, $querystring);
foreach $namval (@arrnameval)
{
   ($nam, $val) = split(/=/, $namval);
   $val =~ tr/+/ /;
   $val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
   $FORMDATA{$nam} = $val;
}





##### Auktionsnummer über referer
if ($FORMDATA{Bild}){  ermitteln
       $querystring = $ENV{HTTP_REFERER};

if ($querystring =~ "&amp;") {$querystring =~ s/amp;//;}
if ($querystring !~ "QQitemZ") {
@arrnameval = split(/&/, $querystring);
} else {
@arrnameval = split(/QQ/, $querystring);
}

foreach $namval (@arrnameval)
{
if ($querystring !~ "QQitemZ") {
   ($nam, $val) = split(/=/, $namval);} else {
($nam, $val) = split(/Z/, $namval);}

   $val =~ tr/+/ /;
   $val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
if ($nam eq "item"){
   $FORMDATA{item} = $val;
}
}
}



$item=$FORMDATA{item};
$fehlermeldung = "<li>Fehler bei der Datenbankverbindung aufgetreten. Bitte ueberpruefen Sie die Angaben";

$dbh = DBI->connect("DBI:mysql:$datenbank:$datenbankhost","$datenbankuser","$datenbankpw") || fehlerausgabe($fehlermeldung);

$sth = $dbh->prepare("SELECT item FROM `blacklist` WHERE item = '$item'");
$sth->execute or die DBI->errstr;
$ergebnis =  $sth->fetchrow_array(); #Wenn EIN Ergebnis erwartet wird
$dbh->disconnect; # DB Connect beenden



if ($ergebnis) {
print "Location: ../grafics/keinBild.gif\n\n";}
else {
print "Location: http://abcde.de/userdaten/$FORMDATA{User}/$FORMDATA{Galerie}/$FORMDATA{Bild}tn.jpg\n\n";
}



Oder mache ich etwas falsch? Ich habe seit ca. 4 Stunden Erfahrung mit sql, so dass natürlich auch diese Möglichkeit besteht :-)
Nur: Im test, also wenn ich es allein versuche, haut alles hin. Erst, wenn hunderte Zugriffe kommen, lahmt es...

Schonam vielen Dank!!
xwolf
 2006-01-20 00:25
#33918 #33918
User since
2005-09-17
51 Artikel
BenutzerIn
[Homepage] [default_avatar]
ALso das der zusätzliche Aufruf von SQL, inklusive der Zeit für den notwendigen Datenbankconnect, schneller sien soll als das was du vorher gemacht hast. halte ich für ein übles Gerücht. Je nachdem, wie fix der Datenbankserver ist, kann allein der Connect bis zu einer Sekunde dauern...

Ich würde erstmal versuchen, woanders zu drehen.
Zum einen beim Apache: Weise den an, allen Bildern ein Expire zuzuordnen.
Wenn dann Surfer die Bilder mehrmals aufrufen oder über einen Proxy gehen, hast du dann weniger Traffik.

Das andere was du machen könntest: Geb den Bildern den Dateinamen der Transaktionsnummer.
Mach dann garnicht erst eine Abfrage ob die Datei existiert, sondern verweise gleich darauf. Ggf. auch garnicht über ein Skript sondern über RewriteRules in der Apacheconf. Das Fehlerbild gibst du auch nicht an, das geht auch besser im Apache:
ErrorDocument 404 /errorbild.jpg
olruebe01
 2006-01-20 00:49
#33919 #33919
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
Hi Xwolf,

Danke für die Tipps, wird aber alles nichts nützen, bzw. nicht gehen, denn...
1: Die Bilder liegen wiederum auf einem anderen Server. DIESER Server ist nur für die Genehmigungen, Statistiken, etc. da und gibt dann ein "Location" auf einen anderen Server aus. Trafik ist also kein Problem.

Dann habe ich viele Powerseller, die EIN Bild in 20 Auktionen verwenden. Hiervon soll aber nur EINE Auktion gesperrt werden. Nach Deiner Methode müsste ich EIN Bild in 20 Kopien anlegen... :-(
Somit fällt auch das 404-Bild weg.

Ich habe eben nochmal ganz genau getstet. Jetzt ist auf dem Server nich soviel los. Der Server hält jetzt - Nachts - zwar durch aber die load average steigt auf etwa 10 und die Prozessorlast liegt bei 100%

Also ist SQL für mich keine Lösung?????

Warum belastet die SQL den Prozessor so stark? Ist das richtig so???
Dubu
 2006-01-20 01:13
#33920 #33920
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Benutzt du denn wenigstens mod_perl (oder vergleichbares fuer deinen Webserver)? Wenn nicht, dann wuerde ich da anfangen.

Und ja, der Datenbankzugriff erzeugt einen deutlichen Overhead, wenn fuer jeden Bildzugriff die Datenbankverbindung auf- und wieder abgebaut werden muss. Da ist dein Dateizugriff deutlich schneller.

Da du aber nur eine sehr simple Datenbank brauchst, waere es vielleicht sinnvoll, z.B. die Berkeley DB oder SQLite in Betracht zu ziehen. Beide haben deutlich weniger Overhead, weil sie nur auf einer Datei mit einem Index beruhen. Du koenntest mal einen Blick auf CPAN:DBD::SQLite und CPAN:DBD::DBM werfen. Oder, wenn es kein SQL sein muss, auf die recht simplen DBM-Implementierungen, auf die in AnyDBM_File verwiesen wird.
olruebe01
 2006-01-20 01:25
#33921 #33921
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
Wäre denn eine solche "sehr simple Datenbank" schneller als mein jetziges System?

Mod_Perl: Ehrlich gesagt: Nein. Ich bin ein bisschen überrant worden und komme mit dem lernen nicht nach. Meine Server sind schneller überlastet als ich eine Lösung finden kann... Um es anders zu sagen: Ich habe keine AHnung was Mod_perl ist...\n\n

<!--EDIT|olruebe01|1137713200-->
ptk
 2006-01-20 01:26
#33922 #33922
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Hast du einen Index auf die zu durchsuchende Spalte?

Und warum schreibst du "use CGI", machst dann das Parameterhandling aber selbst? Außerdem verwendest du keine DBI-Platzhalter, gefährlich!

Eine hohe Last könnte auf zu wenig Speicher hindeuten.

Mit mod_perl lässt sich gegenüber CGI viel gewinnen.
olruebe01
 2006-01-20 01:30
#33923 #33923
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
Wie gesagt: Ich "arbeite" mit SQL seit 4 (inzwischen 7) Stunden!!!

Ja, ich habe den Index richtig gesetzt.

use CGI hatte ich so aus einem Script übernommen mit dem ich angefangen hatte. Habe ich inzwischen alles auf ein Minimum reduziert, hat aber auch nichts geholfen. Der gesammte obere Teil...

Code: (dl )
1
2
3
4
5
use CGI::Carp qw(fatalsToBrowser);
# Dateiflock
use Fcntl qw(:DEFAULT :flock);
use CGI qw(:standard);
use CGI;

...ist inzwischen raus.

Mit Speicher meinst Du sicher den Arbeitsspeicher? 2 GB RAM für ein DB mit 59 kB.
Ronnie
 2006-01-20 01:35
#33924 #33924
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
mod_perl und ein simpler globaler Hash? Ist es im Hash, dann sehr schnelle Antwort - ansonsten nachschauen im Dateisystem und Hash aktualisieren?!
pq
 2006-01-20 13:38
#33925 #33925
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
- wieviele bilder sind es?
- wieviele requests hast du pro sekunde an dein script?
- welcher server hat die hohe load? webserver oder datenbank? oder sind beide auf einer maschine?
- welche mysql-version verwendest du? verwendest du mysql-caching?
das lohnt sich, wenn du viel mehr abfragen hast als änderungen.
- verwende auf jeden fall mod_perl.
- verwende platzhalter
- mach dein skript fit fürs 3. jahrtausend, das sieht noch sehr steinzeitmäßig aus
- beginne mit Wiki:use strict\n\n

<!--EDIT|pq|1137757287-->
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
 2006-01-20 14:31
#33926 #33926
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
Koennte man eventuell eine persistente Datenbankverbindung nutzen? Damit wuerde der Connect fuer jedes Bild ja wegfallen.
<< |< 1 2 3 >| >> 21 Einträge, 3 Seiten



View all threads created 2006-01-19 23:17.