"We are back" « oc.at

Abwicklung von tausenden MySQL-Queries?

tomstig 09.12.2005 - 16:29 1033 4
Posts

tomstig

OC Addicted
Avatar
Registered: Nov 2003
Location: /home/tomstig/
Posts: 1341
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

Here to stay
Avatar
Registered: Feb 2002
Location: Wien
Posts: 4327
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
Bearbeitet von kleinerChemiker am 09.12.2005, 16:37

that

Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11346
1000 Inserts sollten eigentlich in 1-2 Sekunden fertig sein, außer deine Tabellen haben Millionen von Zeilen und 20 Indizes oder so...

Nurmi

OC Addicted
Avatar
Registered: Jun 2000
Location: Linz (Hauptplatz..
Posts: 810
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

Administrator
Legends never die
Avatar
Registered: Aug 2003
Location: nö
Posts: 25691
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.
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz