Optimiser un rand() MySQL en PHP

Vous qui me lisez en cachette jour et nuit, vous devez savoir que le blog a connu des ralentissements car, que voulez-vous, le succès mondial met un peu à genou mon hébergement. Un système de cache un peu rude a déjà été posé. Nouvel objectif : éliminer les appels à la fonction Random de MySQL !

Car voilà, mon gentil hébergeur me le fait savoir par mail, c'est soit je m'en vais en dédié ailleurs que chez eux, soit j'optimise. Et ce qui fait mal sur les sites du domaine tribords.com, ce sont les bouts de scripts qui affichent aléatoirement. Plus une base grossit, plus la fonction rand() de MySQL est longue à traiter. Il faut donc impérativement éliminer ces randoms, sinon c'est le blâme et le bonnet d'âne. Bref, voilà comment j'ai fait !

Demander à PHP de jeter les dés

Notre bon vieux PHP sait très bien faire des tirages au sort. Normalement je devrais pour bien faire récupérer l'identifiant le plus haut de ma table pour connaître la limite haute : le dernier id de mon lot d'enregistrements. Mais c'est une requête en plus, et nous allons voir qu'on va laisser au hasard la possibilité de se planter. Je met donc un chiffre un peu au dessus de mon nombre de lignes en arrondissant. Alors je lui demande :
$jeu_id = rand(0,7000);
Là, je n'en prend qu'un. Pour en prendre un lot, passer tout ça dans un tableau et mettre le nombre d'occurrences que l'on veut pour avoir une liste de nombres. Ensuite on va passer ça à MySQL dans la requête à modifier en éliminant donc le ORDER BY RAND() et en indiquant donc "en dur" les identifiants à sélectionner :
$sql = 'SELECT DISTINCT * FROM latable WHERE machin_id IN ('.$jeuid.')';
Et voilà ! Seulement voilà, dans le cas du blog, j'ai des trous dans mes identifiants, des billets qui ont été supprimés, etc ... Le tirage au sort de PHP peut donc demander à MySQL d'afficher des enregistrements qui n'existent pas en base. Comment faire ? Tout simplement effectuer plus de tirages au sort et ajouter une clause LIMIT à la requête SQL. Pour afficher 3 articles au hasard, on génère ainsi 5 chiffres au hasard. Cela laisse une marge d'erreur importante : il faut que PHP tombe plus de deux fois dans le lot sur des identifiants inexistants pour que l'affichage ne parvienne pas à sortir 3 données. La méthode est un peu roots pour le moment car je viens à peine de m'y pencher et je pense qu'on peut encore optimiser le code. Alors si vous avez des idées, suggestions ou commentaires, je suis partant. D'autant plus que j'ai maintenant à modifier des dizaines de portions de code un peu partout en appliquant ce patch ... allez, je me souhaite bon courage :)

Sommaire