Mysql und PHP - Abfrage extrem langsam

Schagen

Grünschnabel
Hallo!
Der folgende Code dient dazu aus die passenden Angebote, passend zu den vom Benutzer angegebenen Daten, rauszusuchen:

Code:
$sql = "
	SELECT * FROM angebote WHERE 
	kategorie LIKE '%".$kattest."%' AND
	verfdatum ".$zeichen." ".$verf." AND
	mindmenge <= ".$mind." AND
	prodverf LIKE '%".$prod."%' AND
	
	ort LIKE '%".$_POST['ort']."%' AND
	preis >= ".$preisvon." AND
	preis <= ".$preisbis." AND
	erntedatum >= ".$datumvon." AND
	erntedatum <= ".$datumbis." 
	";
	$resulta = mysql_query($sql) OR die(mysql_error());
	$resultc = mysql_query($sql) OR die(mysql_error());
	$blacklist = array();
	while($row = mysql_fetch_assoc($resultc)) {
		$tempplz = getPlzDis(floatval($tplz),floatval($row["plz"]));
				
						if ($tempplz >= $tumkreis){
							$blacklist[] = $row["ID"];
						}

	
	
	}
	$sql = "
	SELECT * FROM angebote WHERE 
	kategorie LIKE '%".$kattest."%' AND
	verfdatum ".$zeichen." ".$verf." AND
	mindmenge <= ".$mind." AND
	prodverf LIKE '%".$prod."%' AND

	ort LIKE '%".$_POST['ort']."%' AND
	preis >= ".$preisvon." AND
	preis <= ".$preisbis." AND
	erntedatum >= ".$datumvon." AND
	erntedatum <= ".$datumbis;
	foreach($blacklist AS $kand)
   {
	$sql = $sql." AND ID != ".$kand;
   }
	
	$sql = $sql." ORDER BY ID DESC 
	 LIMIT 0,5
		
	";

Die zwei Abfragen sind da, weil das ganze durch die Umkreissuche überprüft wird. Limit 5 da die Suchergebnisse auf mehreren Seiten aufgeteilt werden. Das ganze dauert aber beim ausführen ewig. Index ist gesetzt.
 
Hi,

auf die schnelle, bei dir Zeilen 14 und 15:
PHP:
    $resulta = mysql_query($sql) OR die(mysql_error());
    $resultc = mysql_query($sql) OR die(mysql_error());

Warum feuerst die gleiche Abfrage 2x ab?

Ausserdem hast du in Zeile 8 eine SQL-Injection Lücke drin:
Code:
   ort LIKE '%".$_POST['ort']."%' AND

Du verwendest eine POST-Variable ohne Überprüfung.

Grüße,
BK
 
Das mit der SQL Injection ist, weil ich gerade das mit dem Ort geändert habe, nur zum testen, wird nachher natürlich geändert.

Die zweite Abfrage ist ... unnötig. Hab die jetzt entfernt, dauert aber immer noch ewig.

Ich habe erst gedacht das es an der Blacklist, aber selbst wenn ich diese umgehe, indem ich die Umkreissuche nicht benutze dauerts so lange.
 
Hi,

miss mal die einzelnen Schritte deinen Scripts und lass dir die Laufzeiten ausgeben. Dann siehst du besser, an welcher Stelle die meiste Leistung verbraten wird.

Zum Beispiel mit der Funktion microtime().

Grüße,
BK
 
Ein Frage:

PHP:
    $resulta = mysql_query($sql) OR die(mysql_error());
    $resultc = mysql_query($sql) OR die(mysql_error());

welchen Sinn hat denn diese Konstruktion? ^^

Edit
ach schon gut sry^^
 
Wie sieht denn die Tabellenstruktur aus?
Warum sendest du die selbe Abfrage 3 mal?
Was passiert bei getPlzDis(), warum machst du das nicht gleich mit der ersten Abfrage?

Eventuell auch mal die Abfrage mit EXPLAIN ausführen und das Ergebnis hier Posten.

Achja vielleicht:
SQL:
`preis` BETWEEN ".$preisvon." AND ".$preisbis." AND
`erntedatum` BETWEEN ".$datumvon." AND ".$datumbis." AND
`ID` NOT IN (".implode(',', $blacklist).");
 
Zuletzt bearbeitet von einem Moderator:
Hab den Code mit Between und Not in geändert, leider ist das ganze immer noch so langsam.
Im Anhang habe ich die Tabellenstruktur als PDF angehängt.

Edit:
Ergebnis von Explain:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE angebote index NULL PRIMARY 4 NULL 5 Using where
 

Anhänge

Zuletzt bearbeitet:
Also, du holst alle Eintrgäge nach einem Muster. Dann berechnest du mit getPlzDis() einen Wert und vergleichst diesen mit $tumkreis. ggf. wird dann die ID in die Blacklist gesetzt.
Dann rufst du nochmals alle ab die nicht in der Blacklist sind und setzt ein LIMIT auf 5.
Warum rufst du ein Zweites mal ab? Du hast die Daten ja bereits. Nimm doch einfach die ersten 5 die nach deiner Formel nicht in die Blacklist kommen. So hast du nur noch eine Anfrage an die DB
PHP:
$sql = <<<SQL
SELECT 
	*
FROM 
	angebote 
WHERE 
    kategorie LIKE '%{$kattest}%' 
    AND verfdatum  {$zeichen} {$verf} 
    AND mindmenge <= {$mind} 
    AND prodverf LIKE '%{$prod}%' 
    AND ort LIKE '%{$_POST['ort']}%' 
    AND preis >= {$preisvon} 
    AND preis <= {$preisbis} 
    AND erntedatum BETWEEN {$datumvon} AND {$datumbis} 
ORDER BY ID DESC
SQL;

$result = mysql_query($sql) OR die(mysql_error());
$counter=0;
$selectedRows = array();
//Die Anzahl 5 zur Schlaufenbedinnung hinzufügen
while($row = mysql_fetch_assoc($result) && $counter < 5) {
    $tempplz = getPlzDis(floatval($tplz),floatval($row["plz"]));
    //Formel umdrehen. die Nicht-Blacklist sind gefragt
    if ($tempplz < $tumkreis){
    	$selectedRows[] = $row;
    	$counter++;
    }
}

Achja, was ist eigentlich $zeichen?
 
Zurück