Problème d'optimisation de rand ()

Nouveau WRInaute
Bonjour,

Pourrais qu'un m'aider d'optimiser de rand() :

Le premier cas est avec rand() et vous voyez que c'est presque 60,000 rows. Et quand il s'agit d'une base de 200 000, on peut imaginer que c'est lent :?
opt1267015502e.jpg


Le deuxième cas c'est l'affichage normal et la différence est importante :
arx1267015638r.jpg


Merci d'avance :)
 
WRInaute accro
En effet, rand est à éviter. La raison est simple : rand() fait une seconde requête sur votre table, réassigne un nouvel identifiant aléatoire à chacun des enregistrements et les ressors dans l'ordre de cet identifiant aléatoire (donc aléatoirement).

Il n'existe pas de solution miracle en SQL pur.
Une solution pour récupérer un enregistrement aléatoirement (et un seul. A ne pas faire dans une boucle pour récupérer tous les enregistrements :

  • Compter le nombre total d'enregistrements dans la base.
  • Générer un nombre aléatoire situé 1 et le nombre obtenu ci-dessus.
  • Récupérer tous les enregistrements de la base
  • Ne prendre que celui situé en position x

Si aura non pas une seule requête mais deux. Mais cela sera toujours plus rapide qu'un rand.
 
WRInaute accro
[grillé]

C'est clair que c'est de façon générale une très mauvaise idée avec une table un tant soit peu importante: ça oblige le serveur à lire toute la table avant de faire un tri sur ce critère aléatoire (sur toute la table donc) puis d'en extraire juste quelques lignes.

Plusieurs options (qui dépendent beaucoup de ce que tu veux exactement, tu contenu de ta table, de ce que tu sais à propos de ta table...):
- juste prendre (par exemple) les X derniers enregistrements (en supposant que tu aies un index adapté)
- si les enregistrements ont un ID séquentiel et que tu en connais l'étendue, tirer au sort N nombres dans cette étendue, et faire un select * from table where id in (n1,n2,n3...). Si tu as des "trous" dans ta séquence tu peux avoir besoin de fournir un peu plus d'IDs histoire d'en avoir le bon nombre à la fin du compte. evidemment il doit y avoir un index sur id.
- stocker un nombre aléatoire dont l'étendue est connue dans chaque ligne de la table, mettre un index sur cette colonne, et faire une recherche avec colonne_aleatoire > nombre_aleatoire_dans_la_meme_entendue order by colonne_aleatoire limit N

Il y en a probablement plein d'autres...

Jacques.
 
Nouveau WRInaute
Merci dmathieu et Jacques :)

Car les enregistrements sont séquentiels et près qu'il n'y a pas de "trous", j'ai fais de la manière suivante:

- récupérer le plus grand id de la table: select max(id) from table;

- générer avec le php des chiffres aléatoire entre 0 et MAX(id). un peu plus de ce qu'il me faut, mais pour être sure que même s'il y aura de trous, je ferai le tri parmi le nombre assez grand.

- faire une select des rows avec : select * from table where id in ( join(",", $ids) ) limit 20;

merci encore pour votre aide :wink:
 
Discussions similaires
Haut