JeuWeb - Crée ton jeu par navigateur
[PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? (/showthread.php?tid=5939)

Pages : 1 2


RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - Myrina - 25-01-2012

Dans le sens ou je prévois que c'est un script Web qui initie le traitement qui sera exécuté en tâche de fond (fork), normalement, il ne devrait pas y avoir de restriction de temps du point de vue du serveur.


RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - Sephi-Chan - 25-01-2012

Je ne sais pas. Au pire tu utilises un système de queue : tu en auras d'autres usages si ton application est un peu complexe.


RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - Myrina - 27-01-2012

En explorant les différentes possibilités, j'ai trouvé que la commande LOAD DATA INFILE serait 20 fois plus rapide que la commande INSERT. :bave:
Il faut modérer ce ratio par le cout supplémentaire d'écriture dans un fichier au lieu de stocker les différentes VALUES dans une variable (string ou array) avant l'appel de la commande MySQL.

Mais avec le passage par un fichier, la question de limitation de la volumétrie disparait.


RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - php_addict - 27-01-2012

(27-01-2012, 12:46 PM)Myrina a écrit : En explorant les différentes possibilités, j'ai trouvé que la commande LOAD DATA INFILE serait 20 fois plus rapide que la commande INSERT. :bave:

intéressant, si tu utilisera ceci, tu pourra nous dire si c'est vraiment plus rapide stp ?




RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - Myrina - 27-01-2012

Je viens de faire une petit bench:

Citation :INSERT dans boucle :
100 -> 3,7283s
1000 -> 43,6131s
10000 ->

INSERT après boucle :
100 -> 0,0861s
1000 -> 0,1655s
10000 -> 0,6515s
15000 -> 1,0978s

LOAD DATA INFILE :
100 -> 0,0826s
1000 -> 0,16s
10000 -> 0,6896s
15000 -> 1,0418s
Alors, je n'ai pas lancé les 10 000 inserts individuels (sinon j'y serai encore demain...).
J'aurai souhaité monter plus mais, pour une raison que je n'ai pas encore trouvé, ma boucle ne dépasse pas 16383 (2^14 -1).

voici les sources des tests (fait sur un wamp):
1/ INSERT dans la boucle:
Code PHP :
<?php 
list($msec,$sec)=explode(' ',microtime());
$starttime=$msec+$sec;


$link = mysql_connect(BDD_HOST, BDD_USER, BDD_PASS);
if (
is_resource($link)) {
if (
mysql_select_db(BDD_NOM,$link)) {
mysql_query("SET NAMES 'utf8'");
}
}

$tab=array();
$maxx=10000;
$maxy=10000;

for (
$i=0;$i<10000;$i++) {
$ok=false;
while (!
$ok) {
$x=rand(0,$maxx);
$y=rand(0,$maxy);
if (
$tab[$x+$y*$maxy]!=1) {
$tab[$x+$y*$maxy]=1;
$ok=true;
}
}
mysql_query('INSERT into jeu_localisations(galaxie,objet,loc_x,loc_y,symboles,carac) VALUES (1,1,'.$x.','.$y.',\'ABCDE\',\'{"data":"rien"}\')') or die (mysql_error());
}



list(
$msec2,$sec2)=explode(' ',microtime());
$endtime=$msec2+$sec2;
$duree=$endtime-$starttime;
echo
"durée globale: ".round($duree,4);

2/ INSERT à la fin
Code PHP :
<?php 
list($msec,$sec)=explode(' ',microtime());
$starttime=$msec+$sec;


$link = mysql_connect(BDD_HOST, BDD_USER, BDD_PASS);
if (
is_resource($link)) {
if (
mysql_select_db(BDD_NOM,$link)) {
mysql_query("SET NAMES 'utf8'");
}
}

$tab=array();
$maxx=10000;
$maxy=10000;
$rows=array();

for (
$i=0;$i<10000;$i++) {
$ok=false;
while (!
$ok) {
$x=rand(0,$maxx);
$y=rand(0,$maxy);
if (
$tab[$x+$y*$maxy]!=1) {
$tab[$x+$y*$maxy]=1;
$ok=true;
}
}
$rows[]='(1,1,'.$x.','.$y.',\'ABCDE\',\'{"data":"rien"}\')';
}

mysql_query('INSERT into jeu_localisations(galaxie,objet,loc_x,loc_y,symboles,carac) VALUES '.implode(',',$rows)) or die (mysql_error());


list(
$msec2,$sec2)=explode(' ',microtime());
$endtime=$msec2+$sec2;
$duree=$endtime-$starttime;
echo
"durée globale: ".round($duree,4);

3/LOAD DATA INFILE:
Code PHP :
<?php 
list($msec,$sec)=explode(' ',microtime());
$starttime=$msec+$sec;

if (!
defined('SITE_ROOTDIR')) {
define('SITE_ROOTDIR',realpath(dirname(__FILE__)));
}

$link = mysql_connect(BDD_HOST, BDD_USER, BDD_PASS);
if (
is_resource($link)) {
if (
mysql_select_db(BDD_NOM,$link)) {
mysql_query("SET NAMES 'utf8'");
}
}

$tab=array();
$maxx=10000;
$maxy=10000;

$fic=SITE_ROOTDIR.'/data.dump';

$f= fopen($fic, "w");


for (
$i=0;$i<10000;$i++) {
$ok=false;
while (!
$ok) {
$x=rand(0,$maxx);
$y=rand(0,$maxy);
if (
$tab[$x+$y*$maxy]!=1) {
$tab[$x+$y*$maxy]=1;
$ok=true;
}
}
fputs($f,"1\t1\t".$x."\t".$y."\tABCDE\t{\"data\":\"rien\"}\n");
}
fclose($f);
//hack windows
$fic=str_replace('\\','\\\\',$fic);

mysql_query("LOAD DATA INFILE '".$fic."' INTO TABLE jeu_localisations(galaxie,objet,loc_x,loc_y,symboles,carac)") or die (mysql_error());


list(
$msec2,$sec2)=explode(' ',microtime());
$endtime=$msec2+$sec2;
$duree=$endtime-$starttime;
echo
"durée globale: ".round($duree,4);

avec comme table :
CREATE TABLE IF NOT EXISTS `jeu_localisations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`galaxie` int (11) NOT NULL,
`objet` int (11) NOT NULL,
`loc_x` int(11) NOT NULL,
`loc_y` int(11) NOT NULL,
`symboles` varchar(10) collate utf8_unicode_ci NULL ,
`carac` text COLLATE utf8_unicode_ci NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `loc` (`galaxie`,`loc_x`,`loc_y`),
INDEX (`galaxie`),
INDEX (`objet`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

En recoupant une information fournie par Sephi-chan, l'utilisation d'un fichier puis de LOAD DATA INFILE ne serait justifiée par rapport à un INSERT à la fin que pour une volumétrie trop importante: dépassement du tampon



RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - Myrina - 27-01-2012

J'ai trouvé ma limitation à 16384 occurrences: c'est la fonction rand()!

En passant avec :
Code PHP :
<?php 
$x
=mt_rand(0,$maxx);
$y=mt_rand(0,$maxy);
fonction également plus rapide, j'obtiens maintenant :
Citation :INSERT après boucle :
25000 -> 1,3005s
100000 -> MySQL server has gone away
4 x 25000 -> 7,2685s

LOAD DATA INFILE :
25000 ->1,4365s
100000 -> 7,0623s
En fait, à 100 000 enregistrements insérés d'un coup, cela fait environ 4 millions de caractères pour la commande SQL donc plus que accepté par MySQL.


RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - php_addict - 27-01-2012

merci pour ce test, vraiment interessant


RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - Ter Rowan - 27-01-2012

Est ce que y a un équivalent pour les update (autre que par une requête unique qui croise les données d'autres tables via une formule) ?


en tout cas c'est intéressant


RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - php_addict - 27-01-2012

(27-01-2012, 05:44 PM)Ter Rowan a écrit : Est ce que y a un équivalent pour les update (autre que par une requête unique qui croise les données d'autres tables via une formule) ?

lit le manuel: http://dev.mysql.com/doc/refman/5.0/fr/load-data.html il faut préciser REPLACE ou un truc du genre


RE: [PHP/MySQL] Quel est le meilleur nombre d'INSERT simultanés ? - jean-baptiste - 31-01-2012

C'est marrant je me suis confronté au même problème au boulot.
Avec une échelle un peux plus importante. (1.000.000)
Dans tout les cas le faire dans un boucle en individuel est toujours plus lent.
Tout d'abbord il faut bien faire attention à sa structure de table, si tu peux éviter les autoincrements tu gagnes bien sur un peux de temps. De même si ta table est en myIsam.
L'autre avantage de le faire par lot est de controler l'intégrité de tes données au fur et à mesure.

Sinon si tu veux le faire via un fichier cela te permet de gagner bcp de temps( plus tu en as et plus tu gagnes du temps).
J'avais des champs personnellement avec bcp de donnée j'avais générer un fichier de 700Mo.
Je passais de 5 minutes via un fichier à 10aine de minute par lot de 5.000 insertions.

Tout dépend si le temps d'insertion est une priorité pour toi.

J-B