Comment optimiser l'opérateur ORDER BY RAND() ?
sobes.tech IA
Réponse de l'IA
Optimiser ORDER BY RAND() est difficile, car il nécessite une sélection complète des données pour générer un nombre aléatoire pour chaque ligne. Les approches typiques :
-
Sélection d'un identifiant aléatoire :
- Obtenir le nombre de lignes dans la table.
- Générer un nombre aléatoire entre 0 et N-1 (ou 1 et N).
- Sélectionner la ligne avec le décalage correspondant ou
OFFSET.
SELECT COUNT(*) FROM your_table; -- Supposé que le nombre total de lignes = N SELECT * FROM your_table LIMIT 1 OFFSET floor(random() * N);Cette méthode convient pour sélectionner une ou quelques lignes aléatoires. Elle n'est pas efficace pour un grand nombre de lignes.
-
Sélection aléatoire par plage de
id:- Trouver le
idminimum et maximum. - Générer un nombre aléatoire dans cette plage.
- Sélectionner la ligne avec
id >= nombre_aleatoire, en utilisantLIMIT.
SELECT MIN(id), MAX(id) FROM your_table; -- Supposé que min_id, max_id ont été obtenus -- Dans l'application, générer un id aléatoire dans la plage [min_id, max_id] -- Par exemple : id_aleatoire = min_id + floor(random() * (max_id - min_id + 1)) SELECT * FROM your_table WHERE id >= id_aleatoire LIMIT 1;Peut sauter des lignes si des trous existent dans
id. - Trouver le
-
Création d'une table temporaire ou utilisation d'une sous-requête avec tri par nombre aléatoire :
- Sélectionner un sous-ensemble de données ou uniquement
iddans une sous-requête. - Appliquer
ORDER BY RAND()à ce sous-ensemble.
SELECT * FROM your_table AS t1 JOIN (SELECT id FROM your_table ORDER BY RAND() LIMIT 100) AS t2 ON t1.id = t2.id;Réduit la charge si
LIMITest appliqué à la sous-requête. - Sélectionner un sous-ensemble de données ou uniquement
-
Utilisation d'un champ supplémentaire avec un nombre aléatoire :
- Ajouter un champ dans la table pour stocker un nombre aléatoire.
- Mettre à jour périodiquement ce champ pour toutes les lignes.
- Trier par ce champ.
-- Ajouter un champ ALTER TABLE your_table ADD random_sort_key FLOAT; -- Mise à jour périodique UPDATE your_table SET random_sort_key = RAND(); -- Sélection SELECT * FROM your_table ORDER BY random_sort_key LIMIT 10;Nécessite des modifications dans le schéma et dans le processus de mise à jour en arrière-plan.
-
Algorithme de "mélange" (Fisher-Yates) hors de la base de données :
- Sélectionner tous les
id(ou toutes les données si elles sont petites). - Mélanger la liste dans l'application.
- Sélectionner les N premiers éléments.
// Supposé que ids est []int // ids = ... // Obtenir les ids depuis la base de données rand.Shuffle(len(ids), func(i, j int) { ids[i], ids[j] = ids[j], ids[i] }) // Les N premiers éléments de ids sont maintenant aléatoires // Ils peuvent être utilisés pour sélectionner des lignes complètes // SELECT * FROM your_table WHERE id IN (...)Convient uniquement pour des tables avec peu de lignes.
- Sélectionner tous les
Le choix de la méthode optimale dépend de la taille de la table, du nombre de lignes aléatoires nécessaires et du SGBD spécifique. Pour la plupart des cas, lorsque vous devez sélectionner un petit nombre de lignes aléatoires dans une grande table, la combinaison d'obtention des id avec un OFFSET ou WHERE id IN (...) sera plus performante que ORDER BY RAND() en ordre direct.