[RESOLU] Optimisation de script pour controle et insert en sql

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : [RESOLU] Optimisation de script pour controle et insert en sql

Re: Optimisation de script pour controle et insert en sql

par zizou59 » 09 févr. 2016, 22:07

Super Ynx !!! =D>

Enfin, j'ai résolu le problème, un très grand merci à toi pour ton aide, en fait il fallait bien dans la requete (select) je selection avec la clause where (idlink + user), mais aussi dans le in_array(), inclure l'user pour la comparaison tableau !!!

et donc çà donne ceci :
foreach ($datasent as $data) {
  // si le lien n'est pas dans la bdd
  if (!in_array(array($user, $data['link']), $existedLinks) { // <= ic car oui il scanner que les liens, par les liens where (user+idlink) de $existedLinks([0]=>idlink, user, etc ...)
    // si pas déjà ds la bdd insertion des donnees ds la base
    // on ajoute une virgule en fin de ligne pour ajouter d'autres entrées
    $insertValues = '("", "' . mysqli_escape_string($db,$id) . '", "' . mysqli_escape_string($db,$data['link']).'", "'.mysqli_escape_string($db,$data['aTime']).'", vis),';
  }
}
Je marque donc en résolu !!!

j'ai fait un test de rapport d'optimisation
//avant
exemple 12 requetes en 0.06s
//maintenant grace à ynx 2 requetes (select+insert) en 0.003sec

Re: Optimisation de script pour controle et insert en sql

par zizou59 » 09 févr. 2016, 17:24

Merci ynx pour les explications, c'est plus explicite , je vais tester avec ce que tu viens de me donner !!! je te tiens au courant merci.

Re: Optimisation de script pour controle et insert en sql

par ynx » 09 févr. 2016, 15:43

Quelques explications sur l'utilisation de deux boucles dans mon code :

La première boucle sert uniquement à regrouper les liens envoyés par l'utilisateur dans un tableau ($datasentLink), ceci afin de pouvoir réutiliser directement ce tableau avec la fonction implode dans la requête sql (ce qui n'est pas possible avec le tableau $datasent car il s'agit d'un tableau multidimensionnel).
La première requête permet de récupérer les liens dans la base de données qui sont égaux aux liens envoyés par l'utilisateur. Par exemple si le client envoie les liens présents dans le tableau d'exemple $datasent et que la base de données contient les liens http://google.fr/ et http://google.com/, cette requête va retourner un tableau (via fetchAll) contenant ces deux liens.
Une fois que j'ai récupérer les liens existants dans la bdd qui correspondent à des liens envoyés par le client, je parcours alors tous les liens envoyés par le client et j'insère un lien que si celui-ci n'est pas déjà dans la bdd (comme ton premier code). La seule différence ici est qu'au lieu d'exécuter une requête insert pour chaque lien, je regroupe tous les liens à insérer dans une seule requête.

Si tu veux également ajouter une condition sur l'identifiant de l'utilisateur dans la première requête, tu dois pouvoir le faire comme ceci :
$sqlverif = "SELECT idlink FROM user_link WHERE idlink IN ('" . implode("','", $datasentLinks) . "') AND id='" . .mysqli_escape_string($db,$id) . "'";

Re: Optimisation de script pour controle et insert en sql

par zizou59 » 09 févr. 2016, 00:20

Je viens de tester le bout de code à ynx, et çà ne fonctionne pas, il insert quand m^me les lignes dupliqué !!!
c'est chiant car je dois controler par raport à 2 where ( idlink et user)

donc ynx cette partie :
$sqlverif = "SELECT idlink FROM user_link WHERE idlink IN ('" . implode("','", $datasentLinks) . "')";
$query = mysqli_query($db,$sqlverif) or die('ERROR SQL !'.mysqli_error($db));
$existedLinks = mysqli_fetch_all($query);
Donc si je comprend bien, la requete parcours toutes les lignes existante ?

Mis franchement j'ai essayé çà ne fonctionne pas, je suis u'on est pas loin, mais c'est compliqué pour ma petite caboche lol :D

j'ai esayé comme ceci sans resultat :
$sqlverif = "SELECT * FROM user_link WHERE idlink IN ('" . implode("','", $datasentLinks) . "')";
$query = mysqli_query($db,$sqlverif) or die('ERROR SQL !'.mysqli_error($db));
$existedLinks = mysqli_fetch_all($query);
et
$sqlverif = "SELECT * FROM user_link WHERE (idlink AND user) IN ('" . implode("','", $datasentLinks) . "')";
$query = mysqli_query($db,$sqlverif) or die('ERROR SQL !'.mysqli_error($db));
$existedLinks = mysqli_fetch_all($query);
et
$sqlverif = "SELECT * FROM user_link WHERE (idlink AND user='".$id."') IN ('" . implode("','", $datasentLinks) . "')";
$query = mysqli_query($db,$sqlverif) or die('ERROR SQL !'.mysqli_error($db));
$existedLinks = mysqli_fetch_all($query);

Re: Optimisation de script pour controle et insert en sql

par zizou59 » 08 févr. 2016, 22:26

je viens de le faire, à moi que je m'y prends mal, j'ai spécifié champ unique pour LINK et USER ds sql, et voici ma requête php :
// si pas déjà ds la bdd insertion des donnees ds la base
 $sql = 'INSERT IGNORE INTO user_link VALUES ("", "'.mysqli_escape_string($db,$userid).'", "'.mysqli_escape_string($db,$link).'", "'.mysqli_escape_string($db,$time).'", vis)';
Ensuite tu parle de prob index ? en faite ensuite le lien est validé avec le champ(vis) qui pass de 0 à 1.

Re: Optimisation de script pour controle et insert en sql

par or 1 » 08 févr. 2016, 22:09

tu crées donc un index unique sur les champs LINK et USER et alors tu peux faire une seule requête.
bon après, il faut voir si cet index ne va pas ralentir le tout dans d'autres cas de figure, qui sont bien plus fréquents et donc plus problématiques pour le serveur.

Re: Optimisation de script pour controle et insert en sql

par zizou59 » 08 févr. 2016, 21:47

salut or1, tu parle de la solution de Mazarini ?

parce qu'en faite je viens de tester le ignore, mais le probleme c'est que effectivement il bloque avec l'option unique des champs dans sql, or le probleme est qu'il est possible que plusieurs utilisateur ont le m^me lien !!!

ma table est construite de cette façon :

ID|LINK|TIME|USER|VIS

actuelement je boucle une reception array json.

donc comme un gros bourrin, je foreach l'array() json, dans cette boucle je controle 1 par 1 si existe dans base suivant (LINK et USER) et si existe pas on insert ds sql !!!

Donc en gros je demande au spécialiste une méthode non bourrin, afin d'évité le multi-requêtage et soulager mon serveur et ma base !!!

Je sais qu'il existe un moyen de faire une seule requête, un peu du genre comme ynx me l'as démontrer, mais franchement je pige pas trop, de plus il sépare en 2 boucles

Donc le insert ignore ne marchera pas dans mon cas !!! car je peux pas définir un champs unique a part l'id auto-increment.

Re: Optimisation de script pour controle et insert en sql

par or 1 » 08 févr. 2016, 20:34

avec cette méthode plus besoin de la requete select, une seule requete insert avec la syntaxe :
INSERT INTO user_link VALUES
("", "id1", "link1", "time1", vis),
("", "id2", "link2", "time2", vis),
("", "id3", "link3", "time3", vis)
qui n'ajoutera que ce qui ne fait pas doublon.

Re: Optimisation de script pour controle et insert en sql

par zizou59 » 08 févr. 2016, 20:09

Salut Mazari,

Tu as un exemple par rapport a ce que j'ai donné comme code ?

je comprend un peu la logique mais au final on reste sur le m^me nombre de requête ? ou cela réduit le nombre ?

Re: Optimisation de script pour controle et insert en sql

par Mazarini » 08 févr. 2016, 19:09

Bonjour,

Pour faire au plus simple, je crée un index unique sur les colonnes (idlink, id) et je fais chaque insert. En cas d'erreur "duplicate key", j'ignore car c'est qu'il existait déjà.

Re: Optimisation de script pour controle et insert en sql

par zizou59 » 08 févr. 2016, 18:15

Salu ynx, merci d'avoir répondu !!!

je vais tester ton code, en fait le but est optimiser au niveau vitesse mais sql aussi, j'avais déjà regarder sur ce genre de méthode mais je pigé rien !!!

La variable $id => session id de l'utilisateur

Re: Optimisation de script pour controle et insert en sql

par ynx » 08 févr. 2016, 15:51

Salut,

Voici un début d'optimisation possible (code non testé) :
// tableau d'exemple de données reçus
$datasent = array(
	array('link' => 'http://google.fr/', 'aTime' => '123456789'),
	array('link' => 'http://google.com/', 'aTime' => '123456789'),
	array('link' => 'http://google.uk/', 'aTime' => '123456789'),
	array('link' => 'http://google.ca/', 'aTime' => '123456789'),
	array('link' => 'http://google.us/', 'aTime' => '123456789'),
	array('link' => 'http://google.ru/', 'aTime' => '123456789')
); 

// on regroupe les liens envoyés dans un tableau 
$datasentLinks = array();
foreach ($datasent as $data) {
	$datasentLinks[] = mysqli_escape_string($db, $data['link']); // on évite les injections sql
}

// on récupère tous les liens envoyés qui existent déjà en bdd
$sqlverif = "SELECT idlink FROM user_link WHERE idlink IN ('" . implode("','", $datasentLinks) . "')";
$query = mysqli_query($db,$sqlverif) or die('ERROR SQL !'.mysqli_error($db));
$existedLinks = mysqli_fetch_all($query);

// on initialise la chaine qui va contenir la liste des entrées sql (VALUES)
$insertValues = '';

foreach ($datasent as $data) {
	// si le lien n'est pas dans la bdd
	if (!in_array($data['link'], $existedLinks) {
		// si pas déjà ds la bdd insertion des donnees ds la base
		// on ajoute une virgule en fin de ligne pour ajouter d'autres entrées
		$insertValues = '("", "' . mysqli_escape_string($db,$id) . '", "' . mysqli_escape_string($db,$data['link']).'", "'.mysqli_escape_string($db,$data['aTime']).'", vis),';
	}
}

// si on a au moins un lien à ajouter
if ($insertValues) {
	// on supprime la dernière virgule ajoutée à la fin
	$insertValues = substr($insertValues, 0, strlen($insertValues) - 1);
	
	$sqlInsert = 'INSERT INTO user_link VALUES ' . $insertValues;
	mysqli_query($db,$sql) or die('ERROR SQL !'.mysqli_error($db));
}
L'idée est de récupérer dans la variable $existedLinks l'ensemble des liens qui existent déjà dans la base de données en utilisant l'opérateur IN en sql.
Puis on parcours le tableau des données reçues en vérifiant l'existence en bdd via if(!in_array($data['link'], $existedLinks)
Enfin on concatène toutes les valeurs des données à insérer pour n'avoir qu'une seule requête sous la forme suivante :
INSERT INTO user_link VALUES
("", "id1", "link1", "time1", vis),
("", "id2", "link2", "time2", vis),
("", "id3", "link3", "time3", vis)
Par contre je n'ai pas compris d'où venait la variable $id dans ton code ni pourquoi elle est utilisée dans la requête de vérification.

Bonne journée

Optimisation de script pour controle et insert en sql

par zizou59 » 08 févr. 2016, 14:33

Bonjour les ami(e)s !!! :roll:

Je Cherche actuellement à optimiser une partie de mon script, en effet je reçois un array() via la méthode GET, et ensuite je contrôle si les données sont déjà existante avant insert dans la base !!!

Le problème c'est que ma méthode exécute plusieurs fois la requêtes, et je sais que c'est pas bon, que l'on peut optimiser tout çà en une seule requête mais je ne sais pas comment.

Donc je demande aux experts de me mettre sur la voie afin que j’exécute une seule requête pour l'ensemble de mon array().

Voici le code :
// definition des variables
$id = $_SESSION['sessionutilisateur'];


// test si get existe et n'est pas null
if(isset($_GET['datasend']) && $_GET['datasend'] != NULL) {
	
	// definition de variable array $datasent recu pour exemple
	$datasent = '[
	{"link":"http://google.fr/", "aTime":"123456789"},
	{"link":"http://google.com/", "aTime":"123456789"},
	{"link":"http://google.uk/", "aTime":"123456789"},
	{"link":"http://google.ca/", "aTime":"123456789"},
	{"link":"http://google.us/", "aTime":"123456789"},
	{"link":"http://google.ru/", "aTime":"123456789"}
	]';
	
	$someArray=json_decode($datasend, true);
    foreach ($someArray as $key => $value) {
	$link=$value["link"];
	$time=substr($value["aTime"], 0, 10);
	
	// on verifie si le lien n'existe pas déjà par rapport à l'user
    $sqlverif = "SELECT * FROM user_link WHERE (idlink='".mysqli_escape_string($db,$link)."' AND id='".$id."')";
    $query = @mysqli_query($db,$sqlverif) or die('ERROR SQL !'.mysqli_error($db));
    $count_link = @mysqli_num_rows($query);
	
	// condition de test si pas ds la base (si différent de 1 on insert)
	if($count_link < 1){
		
	// si pas déjà ds la bdd insertion des donnees ds la base
    $sql = 'INSERT INTO user_link VALUES("", "'.mysqli_escape_string($db,$id).'", "'.mysqli_escape_string($db,$link).'", "'.mysqli_escape_string($db,$time).'", vis)';
    @mysqli_query($db,$sql) or die('ERROR SQL !'.mysqli_error($db));
		
	} // fin condition de test si existe ds la base
	
	} // fin boucle foreach
	
} // fin condition get
Merci par avance...