Refaire cette requete plus rapidement (mysql)

Baboo
Invité n'ayant pas de compte PHPfrance

23 mai 2008, 02:06

Bonjour j'ai dans une page index plusieurs include, hors un de c'est include comporte des requetes dans ma base de donnée et cela fait que ma page s'affiche apres 5 secondes ce qui est enorme.

Le bout en question est dans une boucle foreach

			$con = mysql_connect('localhost','Video','video');
			$UpdateSql = "UPDATE Video SET  `VideoId` = '$id', `Title` = '$title', `VideoUrl` = '$rurl', `Channel` = '$type', `ChannelUrl` = '$typeurl', `DateFound` = '$datefound', `Description` = '$description', `Actor` = '$actor', `Director` = '$director', `Writer` = '$writer', `Producer` = '$producer', `Artist` = '$artist', `Album` = '$album', `Author` = '$author', `Rating` = '$rating', `Runtime` = '$runtime', `Category` = '$category', `Tags` = '$tags', `ShowName` = '$showname', `ShowUrl` ='$showurl', `EpisodeName` = '$episodename', `EpisodeNumber` = '$episodenumber, `SeasonNumber` = '$seasonnumber, `Country` = '$country', `Language` = '$language', `DateProduced` = '$dateproduced', `ViewCount` = '$viewcount', `UserRating` = '$userrating', `UserRatingCount` = '$userratingcount', `VideoEmbed` = '$link', `Quality` = '$quality', `Filesize` = '$size', `Adult` = '$adult' WHERE `Channel` = '$type' AND `Title`= '$title' ";
			

			$InsertSql = "INSERT INTO `Video` (`Id`, `VideoId`, `Title`, `VideoUrl`, `Channel`, `ChannelUrl`, `DateFound`, `Description`, `Actor`, `Director`, `Writer`, `Producer`, `Artist`, `Album`, `Author`, `Rating`, `Runtime`, `Category`, `Tags`, `ShowName`, `ShowUrl`, `EpisodeName`, `EpisodeNumber`, `SeasonNumber`, `Country`, `Language`, `DateProduced`, `ViewCount`, `UserRating`, `UserRatingCount`, `VideoEmbed`, `Quality`, `Filesize`, `Adult`) VALUES (NULL, '$id', '$title', '$rurl', '$type', '$typeurl', '$datefound', '$description2', '$actor', '$director', '$writer', '$producer', '$artist', '$album', '$author', '$rating', '$runtime', '$category', '$tags', '$showname', '$showurl', '$episodename', '$episodenumber', '$seasonnumber', '$country', '$language', '$dateproduced', '$view', '$userrating', '$userratingcount', '$link', '$quality', '$size', '$adult');";

			if (!$con)
            {
            die('Could not connect: ' . mysql_error());
            }
			
            mysql_select_db("Video", $con);
			
            $query = "SELECT Id FROM Video WHERE title='$title' AND channel= '$type'";
            $result = mysql_query($query);
            		
			if (!mysql_fetch_row($result)) {
            //noting so we need to add it
			mysql_query($InsertSql);
			$InsertId = mysql_insert_id();
			}
			else
			{
			mysql_query($UpdateSql);
		    $result = mysql_query($query);
	        $row = mysql_fetch_row($result);
		    $InsertId = $row[0];
            	
            }


			
            mysql_close($con);


Pour chaque enregistrement je verifie si l'info est dans la base sinon je l'ajoute si l'info est la je la met a jour.

Pour l'instant ma base contient 100 000 enregistrement mais vous pouvez compter 10 000 de plus chaque jour.

Donc avez vous une suggestion pour amélioré grandement ce code ?
Pui-je faire en sorte d'afficher ma page et ensuite entrer les info dans la base de donnée ?

Merci d'avance

Mammouth du PHP | 881 Messages

23 mai 2008, 05:03

Il n'y a pas de foreach dans le code que tu présentes ci-haut.

Ta table a-t-elle un index? Si non, tu pourrais lui faire un index sur plusieurs champs et donner la propriété "Unique" à cet index. Il te suffirait alors de faire un "Insert" systématique avec toutes les données soumises. Sur message d'erreur, alors tu pourrais faire appel à ta fonction "Update" Ainsi, tu sauverais l'étape de lecture/vérification des existantes.
Soyez artisans de paix

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

23 mai 2008, 07:47

Bonjour,

Au lieu de faire un SELECT puis INSERT ou UPDATE, n'est-il pas possible d'utiliser la commande "tout-en-un" REPLACE:
http://dev.mysql.com/doc/refman/5.0/fr/replace.html

:)
Quand tout le reste a échoué, lisez le mode d'emploi...

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 mai 2008, 11:06

Il n'y a pas de foreach dans le code que tu présentes ci-haut.
D'après ce qu'il dit, tout le code ci-dessus se trouve dans le foreach ;)

Tu pourrais d'ailleurs gagner beaucoup en ouvrant la connexion une fois pour toute (et en sélectionnant la base) en dehors de la boucle plutôt que de la ré-ouvrir à chaque itération (et mettre le close en dehors).

Maintenant un index sur les champs title et channel te permettrait d'aller plus vite pour le select, mais ralentirait l'update/insert.
Pour gagner du temps sur l'update, lorsque tu as testé si l'enregistrement existant, tu en récupère l'identifiant (clé primaire).
Plutôt que repasser les deux infos title et channel dans la condition de l'update utilise la clé primaire il ira beaucoup plus vite à trouver l'enregistrement concerné.
Si tu n'utilise pas le $InsertId dans ta boucle, alors ne fait pas inutilement appel à mysql_insert_id() ou mysql_fetch_row($result) :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 881 Messages

23 mai 2008, 19:26

Bonjour,

Au lieu de faire un SELECT puis INSERT ou UPDATE, n'est-il pas possible d'utiliser la commande "tout-en-un" REPLACE:
http://dev.mysql.com/doc/refman/5.0/fr/replace.html

:)
Merci, ça me servira aussi. Je n'avais jamais vu la fonction REPLACE.
Elle est le meilleur choix, c'est certain.
Soyez artisans de paix

Invité
Invité n'ayant pas de compte PHPfrance

23 mai 2008, 22:48

Merci a vous tous pour vos reponse je vais testé pour voir ce qui me sauveras du temps precieux.

Mais j'y pense existe t-il un moyen de faire un update et de s'avoir si il y a eu bel et bien un update ?

Donc je pourais faire

if(update==true){
//rien}
else{
//inserer car n'existe pas
}

Cela ne sauvrais t-il pas du temps ?
(je suis pas fort coté mysql)

Merci encore a tous

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

23 mai 2008, 23:00

Cette logique est bien car le pourcentage de mise à jour est beaucoup plus important que le nombre d'insertion. Partons sur un 80%/20%

Donc, dans 80% du temps, tu auras une seule requête, et dans les 20% restants, 2 requêtes.
Alors que le REPLACE exécute tout le temps 2 requêtes. Après, le REPLACE fait tout en interne, donc 2 requêtes dans le REPLACE seront plus rapides que 2 requêtes exécutées en PHP, mais je pense que la différence est négigable et que ta solution reste celle qui exécute le moins de requête ;)
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Invité
Invité n'ayant pas de compte PHPfrance

24 mai 2008, 00:08

En fait je dirais que sur mon site le ration insert/update serais plutot de 70%/30%

Mais une question sur le Replace : va t"il changer le numero d'id ? (qui lui est a auto increment)

Car si mon enregistrement par exemple 54 555 devient 200 545 je me retrouve avec une page vide pour les internaute qui eux aurais comme lien 54 555 ....

Invité
Invité n'ayant pas de compte PHPfrance

24 mai 2008, 00:32

Voila la solution du probleme :
$query = "SELECT Id FROM Video WHERE title='$title' AND channel= '$type'"; 
Changer pour :
$query = "SELECT Id FROM Video WHERE title='$title' AND channel= '$type' LIMIT=1"; 
Moi comme pauvre con je lui faisait lire mes 100 000 enregistrements meme si il en avait déja trouvé une !

Je vient de passer d'un temps moyen de chargement de 6 secondes a 0.200 secondes !
Je vais tout de même approfondir mes connaisance avec ce message.

Merci encore a tous

Mammouth du PHP | 881 Messages

24 mai 2008, 06:38

Pour voir s'il y eut update ou non dans ton formulaire, tu peux mettre une case à cocher non-sélectionnée à tous les items. Aux items qui seront modifiés, tu feras (javascript ou ajax) mettre un crochet dans la case. Ensuite, lors de la soumission du formulaire, tu n'auras qu'à traiter les lignes où la case "update" est sélectionnée.
Soyez artisans de paix

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 mai 2008, 10:53

Mais j'y pense existe t-il un moyen de faire un update et de s'avoir si il y a eu bel et bien un update ?
mysql_affected_rows() retourne le nombre de lignes affectées lors de la dernière requête INSERT, UPDATE, REPLACE ou DELETE :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...