Récemment, j'ai eu besoin de mettre à jour des champs si ceux-ci existaient ou de les insérer dans le cas contraire. En soi, ce n'est pas compliqué. Il suffit de tester si les entrées existent, si oui, on les met à jour, sinon on les ajoute.

Voici une structure de table pour l'exemple :

Table statsvisit
id page_id visites date_enregistrement
1 55 152 25-10-2012 00:00:00
2 56 189 25-10-2012 00:00:00

Le but est de mettre à jour le champ visites correspondant à une page page_id à une date t. A une date t+1, nous ajouterons des entrées. Dans une même journée, le nombre de visites sera mis à jour.

 

La solution simple pour insérer ou mettre à jour des données en PHP/MySQL

$date = '2012-11-12 00:00:00';

$request = mysql_query("SELECT id FROM statsvisit WHERE page_id=55 AND DATE(date_enregistrement)='$date'");

$num_rows = mysql_num_rows($request);
if ($num_rows > 0) {
$row = mysql_fetch_array( $request);
$request = mysql_query("UPDATE statsvisit SET visites=$newvalue WHERE id=".$row["id"]);
} else {
$request=mysql_query("INSERT INTO statsvisit (page_id,visites,date_enregistrement) VALUES(55,$newvalue,'$date');
}

L'inconvénient de cette méthode est le temps d'exécution. On effectue deux requêtes sur la base ce qui consomme du temps processeur. Pour une petite table, le problème ne se pose pas mais lorsque le volume de données prend de l'importance, il faudrait essayer de trouver une solution plus optimisée. L'idéal serait de n'avoir qu'une seule requête. L'air de rien, on passerait à 50% de requêtes en moins!
Voici une requête qui fait le boulot :

$request = mysql_query("INSERT INTO statsvisit (page_id, date_enregistrement, visites) VALUES (55,'25-10-2012',".$newvalue.") ON DUPLICATE KEY UPDATE counter= $newvalue");

En gros, la requête va se charger de mettre à jour une ligne de la table si une clé est déjà présente sinon elle ajoutera une ligne. Dans le cas de cette requête, il faut définir une clé unique sur la table.

CREATE TABLE IF NOT EXISTS statsvisit ( 
id INT NOT NULL AUTO_INCREMENT,
page_id int(11),
visites int(11),
date_enregistrement datetime,
PRIMARY KEY(id),
UNIQUE doc_date(page_id, date_enregistrement))

Ici, la clé est basée sur 2 champs : page_id et date_enregistrement.

J'ai testé rapidement le temps d'exécution de ces 2 solutions et la différence est bien nette surtout pour la mise à jour. J'ai réalisé un script qui réalise une boucle de 100 itérations d'abord pour insérer les données puis pour mettre à jour les données. Voici les résultats :

Insertion de données

  • Méthode 1 : 0.040201s
  • Méthode 2 : 0.017952s

Mise à jour de données

  • Méthode 1 : 0.076179s
  • Méthode 2 : 0.022676s

 

Quelques liens utiles