tri de table

roberto
Invité n'ayant pas de compte PHPfrance

11 juin 2007, 10:59

Bonjour,

Je me pose une question et j'aimerai partager mon avis avec vous.
Imaginons que nous ayons une table avec differents attributs (nom, effectifs, ville, date...) et que nous proposons aux users de pouvoir afficher cette table par differents mode d'affichage:
  • par ordre alphabetique des noms
  • par ordre alphabetique des villes
  • par date croissante
  • date decroissante
etc....

J'ai trouvé deux solutions.

La 1ere consiste a afficher la liste normalement a mettre des liens sur la page et d'effectuer les requetes en fonctions des liens.
La 2eme consiste a ne faire une seule requete, a tout mettre dans un tableau multidim et a utiliser les fonctions de tri des tableaux...

Quelle methode vous parait meilleur par rapport a l autre et pourquoi?

Merci.

ViPHP
ViPHP | 928 Messages

11 juin 2007, 11:27

Ben MySQL a déjà des fonctions de tris intégrées, pourquoi réinventer la roue ?

Code : Tout sélectionner

SELECT * FROM ta_table ORDER BY ville DESC, nom ASC
par exemple.

Roberto
Invité n'ayant pas de compte PHPfrance

11 juin 2007, 11:35

Yep, je sais, mais disons que je regarde quelle méthode est la plus efficace pour une bdd enorme...
Les requete mangent beaucoup de ressource.

Eléphant du PHP | 332 Messages

11 juin 2007, 11:41

Par tri des tableaux, on va supposer que tu parles de tri de tableaux en PHP sur le serveur.De toute façon, dans ce cas, tu vas être obligé de faire un appel à ton serveur pour qu'il te renvoie du code HTML généré par PHP avec les données triées dans le bon ordre.
la structure de ta page est donc

Code : Tout sélectionner

1) Lire l'argument de tri 2) Récupérer les données 3) Trier les données 4) Mettre les données en forme 5) Renvoyer une page formée au browser
Si je comprends bien, tu veux une comparaison sur les étapes 2 et 3
--> Solution tri en tableau :
Etape 2
La première fois, tu es obligé de lire les données dans la base. Puis, tu les stockes dans une variable de session
Les fois suivantes, tu vérifies que ton tableau est en variable de session et tu l'utilises directement sans lire dans la base
Etape 3 :
Tu appliques des fonctions de tri dans ton tableau multidimensionnel pour trier les colonnes.

Avantage :
-tu n'as lu ta base qu'une seule fois sans se soucier du tri
Inconvénients :
-tu es obligé de conserver ton tableau en variable de session autant de fois qu'il y a d'utilisateurs connectées
-tu vas écrire des fonctions callback pour les tris usort() selon les colonnes

--> Solution select avec order by
Les étapes 2 et 3 sont mélangées puisque le tri est inclus dans la requête
Avantages :
- tout est inscrit dans la requête
- rien n'est conservé en mémoire du serveur après l'envoi de la page au browser
Inconvénients :
- En SQL tu dis que tu tries sur la colonne A, puis sur la colonne B, ... ce qui laisse moins de possibilités que des tris plus sophistiqués que tu pourrais écrire dans une fonction callback (mais est-ce vraiment nécessaire dans ce cas).
- Tu fais un accès à la base de données à chaque affichage de page

Bref, à moins que tu aies une base surchargée avec des centaines d'utilisateurs simultanés qui s'amusent à trier ton tableau de milliers de communes, la solution 2 est quand même nettement la meilleure, que ce soit au niveau de l'efficacité que celui de la lisibilité du code.

Tu peux également regarder vers le XML/XSL qui permet d'effectuer des tris en local sans avoir besoin de recharger la page, :roll: mais là, je laisse parler les spécialistes.
Regarde cet exemple très simple de tri d'élèves par note (Test 5), par age (test 6) et par ordre alphabétique (Test 7) (l'exemple ne semble fonctionner que pour IE)

Roberto
Invité n'ayant pas de compte PHPfrance

11 juin 2007, 11:55

Merci pour ses réponse.

Pour le moment, ma base de données n'est pas surchargee, mais j'essaye d'optimiser un script pour une entreprise qui aura elle une base enorme....

voici ma fonction de tri utilisant les fonctions de tri de php:
function tri($tri)
{
	$sql=mysql_query("select * from entreprise");
	while($result=mysql_fetch_array($sql))
	{
		$donnee[]=$result;
	}
	foreach ($donnee as $key => $row) 
       {
           $id[$key]  = $row['id'];
	   $nom[$key] = $row['nom'];
	   $lieu[$key]=$row['lieu'];
	   $date[$key]=$row['dateS'];
	
        }
	if( $tri==0)
		array_multisort($date, SORT_ASC, $donnee);
	if ($tri==1)
		array_multisort($nom, SORT_STRING, $donnee);
	if ($tri==2)
		array_multisort($id, SORT_ASC, $donnee);
	if ($tri==3)
		array_multisort($lieu, SORT_STRING, $donnee);
	
	for($i=0;$i<=30;$i++)
		echo $donnee[$i][0].$donnee[$i][1].$donnee[$i][2].$donnee[$i][3].'<br/>';
	

}
Y a quelque point a refaire:

J'aime pas trop la sequence des if et j'ai un while, un foreach et un for...

Merci

Eléphant du PHP | 332 Messages

11 juin 2007, 12:01

Autre idée qui ne fonctionne que si les données varient peu (par exemple, une liste de communes dans un département) et que si les utilisateurs demandent toujours à peu près la même chose.

A chaque mise à jour des données (qui, je le rappelle, ne doivent pas changer trop souvent), tu relis les données avec un select order by ... un coup trié par nom, un coup trié par ville, ... et tu stockes dans des tableaux PHP.

Puis tu enregistres les tableau sur le disque dur dans un fichier tri_par_nom.txt, tri_par_ville.txt, ... Une fonction très utile est la fonction serialize() qui transfome ton tableau en chaîne de caractères.

Par la suite, au lieu d'attaquer la base de données (qui est très chargée selon ce que tu nous dis), tu lis le "bon" fichier texte, puis tu unserialize() pour retrouver un tableau trié.

Tu remplaces de la charge sur la base de données par de la lecture de fichier sur le disque dur du serveur.

Dans la même veine d'idées, pourquoi ne pas générer directement le HTML nécessaire pour les listes ? C'est ce qu'on fait parfois par exemple sur des sites de contenu : un admin met en place des actualités, les modifie une ou deux fois, puis ne les touche plus jamais. La solution classique serait qu'à chaque fois qu'un internaute affiche la page de l'actualité de telle ou telle date, on relise la base de données et qu'on recompose la page HTML. Une autre solution, c'est que chaque fois que l'admin crée ou modifie l'actualité, on regénère complètement la page HTML et on la stocke sur le disque dur. Puis c'est cette page toute prête qui est envoyée à l'internaute sans aucun accès à la base de données.

ROberto
Invité n'ayant pas de compte PHPfrance

11 juin 2007, 12:06

OUi OUi j'avais pensé au bon vieu fichier txt.
Cependant, il me semble qu'il est limité d'acces.

Ma mission est de redonner du trafic au site, donc, j'dois optimiser tous les scripts existants pour accélérer leur temps d'execution.

Je suis preneur de toutes les idées que je n'aurai pas eu comme ta dernière.
A moi maintenant de faire les tests nécessaires.

Roberto
Invité n'ayant pas de compte PHPfrance

11 juin 2007, 12:13

Y a t il un moyen pour ne pas utiliser le foreach dans ma fonction tri.
Pour le moment, je met le tout dans un tableau a 4 dimensions. Apres je crée 4 tableaux et je les tri en fonction du choix de l'utilisateur.

Ne peut on pas faire l'étape 1 et 2 en une fois?

Merci.

Roberto
Invité n'ayant pas de compte PHPfrance

11 juin 2007, 13:52

J'ai surchargé autant que possible ma table (environ 20 000 enregisitrement) et le systeme Mysql est beaucoup plus rapide que celui des fonctions de tri de php.

Je me doute que mon script n'est pas optimal et ceci explique cela...

En tout cas merci.

ViPHP
ViPHP | 5924 Messages

11 juin 2007, 14:25

Dans l'immense majorité des cas, le serveur SQL sera plus rapide que PHP. Le serveur SQL est compilé, PHP est interprété... En placant des index sur les bons champs, c'est le jour et la nuit, à fortiori sur des volumes de donnée immenses. Sachant en plus que tu feras exploser l'usage de ram et de processeur avec des traitements php, alors que MySQL résistera plus facilement. Enfin au passage, des bases de 20 000 enregistrements, ce sont encore des petites bases. Les bases de données peuvent, même sous MySQL, atteindre plusieurs TeraOctets de données...

Roberto
Invité n'ayant pas de compte PHPfrance

11 juin 2007, 19:28

AH Ok Ok, par contre, je fais que d'entendre cette histoire d'index dans les bases de données mais personne ne sait me l'expliquer.
J'ai fait un explain ma table est j'ai eu ceci:

Code : Tout sélectionner

Field Type Null Key Default Extra id int(11) NO MUL NULL auto_increment nom varchar(255) NO PRI lieu varchar(255) NO PRI dateS date NO PRI 0000-00-00 commentaire text YES NULL
Pouvez vous m'en dire plus sur les index?

Merci

ViPHP
ViPHP | 5924 Messages

11 juin 2007, 19:55

Les champs sur lesquels placer des index sont les champs où pour une raison ou une autre, il y aura beaucoup de comparaisons, c'est à dire sur les champs où tu vas utiliser des ORDER BY, des WHERE `machin`>'truc' ou JOIN `trucmuche` ON trucmuche.machin=truc.machin...
Car les serveurs SQL font des tables pour les champs indexés qui leur permettent de faire des recherches beaucoup plus rapides pour certaines requètes, celles où le fait d'avoir des données triées est utile.