Abwicklung von tausenden MySQL-Queries?

Seite 1 von 1 - Forum: Coding Stuff auf overclockers.at

URL: https://www.overclockers.at/coding-stuff/abwicklung_von_tausenden_mysql-queries_154196/page_1 - zur Vollversion wechseln!


tomstig schrieb am 09.12.2005 um 16:29

Also...

Ich hab für die Schule eine Umfrage programmieren müssen. Das ganze habe ich mit PHP gemacht.
Schüler können die 100 Fragen ausfüllen und dann abschicken.
Wenn jetzt aber 10 Schüler gleichzeitig abschicken, dann sind das ja 10x100 Antworten, die in die DB geschrieben werden müssen.
Derzeit geh ich mit einer foreach Schleife alle Antworten durch und speichel sie einzeln mit INSERT.
Das dauert aber ewig (merkt man daran, dass man nachdem man auf Senden klickt, eigentlich auf eine Ergebnisseite gelangen sollte, aber das dauert ewig).
So, meine Frage: Wie löst man das am besten?
Soll man den gesamten Query auf einmal (mit ; getrennt) schicken? Oder gibts eine andere Lösung?

Zu sehen gibts das ganze unter http://tomstig.to.funpic.de/umfrage/ .
Wenn man sich mit dem usernamen "test" und mit pw "eins" anmeldet, kommt man in den "Ausfüll-Modus", mit pw "zwei" in den Adminbereich.

Code, der die Antworten in die DB einträgt, schaut so aus:

Code: PHP
foreach($_POST as $question_id=>$v)
{	
	if( $question_id != 'submit' )
	{	
		$db->sql = "SELECT num_ans FROM questions WHERE group_id=" . $_SESSION['group_id'] . " AND question_id=" . $question_id;
		$db->query();
		$num_ans = $db->single_result();
		
		if( $num_ans != -1 || is_array($v) )
		{								
			if( is_array($v) )
			{
				foreach($v as $k=>$answer_id)
				{
					$db->sql = "INSERT INTO user_answers SET group_id=" . $_SESSION['group_id'] . ", user_id=" . $_SESSION['user_id'] . ", question_id=" . $question_id . ", answer_id=" . $answer_id;
					$db->query();
				}
			}
			else
			{
				$answer_id = $v;
				$db->sql = "INSERT INTO user_answers SET group_id=" . $_SESSION['group_id'] . ", user_id=" . $_SESSION['user_id'] . ", question_id=" . $question_id . ", answer_id=" . $answer_id;
				$db->query();
			}
			
		}
		else
		{
			$db->sql = "INSERT INTO answers SET group_id=" . $_SESSION['group_id'] . ", question_id=" . $question_id . ", type='comment', answer='" . $v . "'";
			$db->query();
			
			$db->sql = "SELECT answer_id FROM answers ORDER BY answer_id DESC LIMIT 1";
			$db->query();
			$answer_id = $db->single_result();
			
			$db->sql = "INSERT INTO user_answers SET group_id=" . $_SESSION['group_id'] . ", user_id=" . $_SESSION['user_id'] . ", question_id=" . $question_id . ", answer_id=" . $answer_id;
			$db->query();	
		}
	}
}
(arrays werden verwendet, damit multiple choice questions eingetragen werden können)

Ich hatte noch die Überlegung, dass in eine Tabelle von jedem user einmal ALLE antworten eingetragen werden (mit z.b. question_id-->answer_id, also "64-->233") und anschließend werden alle nochmal durchgearbeitet (dadurch wird es möglich, dass man den Status ala "60/90 Antworten eingetragen", "61/90"...).

Was meint ihr, ist die beste Lösung?


kleinerChemiker schrieb am 09.12.2005 um 16:35

ich würds in einem query machen:

Code:
INSERT INTO table (field1, field2, ...) VALUES (value1, value2, ...), (value1, value2, ...), (value1, value2, ...), ........

und falls du mysql >=4.1 und PHP5.x hast, könntest du auch prepared statement versuchen.

hth

mik


that schrieb am 09.12.2005 um 20:45

1000 Inserts sollten eigentlich in 1-2 Sekunden fertig sein, außer deine Tabellen haben Millionen von Zeilen und 20 Indizes oder so...


Nurmi schrieb am 10.12.2005 um 09:32

statt

Code: PHP
			$db->sql = "SELECT answer_id FROM answers ORDER BY answer_id DESC LIMIT 1";
			$db->query();
			$answer_id = $db->single_result();

könntest auch

$answer_id = mysql_insert_id();

verwenden (Ich glaub zumindest dass es sich bei "answer_id" um den auto_increment-Wert der Tabelle handelt)

wird geschwindigkeitsmäßig vielleicht ein bischen was bringen - (aber wahrscheinlich nicht spürbar...)

MfG
NuRmi


mat schrieb am 10.12.2005 um 14:41

Zitat von kleinerChemiker
Zitat von BeatMaster
Selbst mit VISA hat man Probleme, zumindest ich mit Blizzard :bash:

"Payment rejected"
das würde ich nicht machen.. man wird bei diesem versuch schnell merken, dass man an die grenzen von mysql stösst. das insert sollte gebuffert werden, also in batches zu x rows ausgeführt werden.




overclockers.at v4.thecommunity
© all rights reserved by overclockers.at 2000-2025