la sélection rapide d'une ligne au hasard à partir d'une grande table dans mysql
Ce qui est un moyen rapide pour sélectionner une ligne au hasard à partir d'une grande table mysql?
Je travaille en php, mais je suis intéressé par toute solution, même si c'est dans une autre langue.
double possible de MySQL sélectionner 10 lignes aléatoires de 600K lignes rapide
OriginalL'auteur lajos | 2008-10-17
Vous devez vous connecter pour publier un commentaire.
Saisir toutes les id, choisir aléatoirement l'une d'elle, et de récupérer la ligne complète.
Si vous connaissez l'id sont séquentielles sans trous, il vous suffit de prendre le max et de calculer un id aléatoire.
Si il y a des trous ici et là, mais surtout les valeurs séquentielles, et vous n'avez pas de soins sur un légèrement de travers à l'aléatoire, saisir la valeur max, calculer un id, et sélectionnez la première ligne avec un id égal ou supérieur à celui que vous avez calculé. La raison de l'inclinaison, c'est que l'id est à la suite de tels trous auront plus de chance d'être sélectionnées que ceux qui suivent une autre id.
Si vous commandez par hasard, vous allez avoir un terrible tableau-scan sur vos mains, et le mot rapide ne s'applique pas à une telle solution.
Ne pas le faire, ni si vous commandez par un GUID, il a le même problème.
OriginalL'auteur Lasse Vågsæther Karlsen
Je savais qu'il y avait un moyen de le faire en une seule requête dans une voie rapide. Et c'est ici:
Un moyen rapide, sans engagement de code externe, bravo à
http://jan.kneschke.de/projects/mysql/order-by-rand/
Oui, vous pouvez obtenir une meilleure répartition si les touches sont sans lacunes et d'éviter les clauses where et ORDER BY. Consulter l'article, c'est assez bien expliqué. Je ne voulais pas voler tout ça, ce n'ai pas mis les autres requêtes, les avantages et les inconvénients de chacun.
Cette requête en quelque sorte de ne pas renvoyer des données à un certain moment, quand vous pouvez spécifier certains paramètre supplémentaire, comme par exemple LORSQUE r1.id >= r2.id ET r1.some_field=1 tandis que some_field contient des données=1. Une idée sur comment résoudre ce problème?
OriginalL'auteur Vinko Vrsalovic
MediaWiki utilise un truc intéressant (pour Wikipédia Spéciales:fonction Aléatoire): le tableau avec les articles a une colonne supplémentaire avec un nombre aléatoire (généré lorsque l'article est créé). Pour obtenir un article aléatoire, générer un nombre aléatoire et obtenir de l'article avec la prochaine plus grande ou plus petite (ne me souviens pas qui) valeur du nombre aléatoire de la colonne. Avec un index, ce qui peut être très rapide. (Et MediaWiki est écrit en PHP et développé pour MySQL.)
Cette approche peut poser un problème si les chiffres sont mal réparties; IIRC, cela a été corrigé sur MediaWiki, donc si vous décidez de le faire de cette façon, vous devriez jeter un coup d'oeil au code pour voir comment c'est fait actuellement (probablement, ils régénérer périodiquement le nombre aléatoire colonne).
sa bonne idée, mais pour les N résultats souhaités peuvent ne pas fonctionner, je suppose.Parce que vous pourriez obtenir moins de résultats ou de l'ordonnance pourrait être tha même.
C'est une belle idée. Mais sur la requête, nous avons encore à trier par le hasard de la colonne, à droite? Supposons que le hasard de la colonne est random_number, alors la requête est comme: "SELECT * from mytable where random_number>$rand COMMANDE PAR random_number LIMITE de 1". Est-il beaucoup plus rapide que la COMMANDE RAND()?
Vous avez besoin de placer un degré de limitation sur le maximum de votre nombre aléatoire en ce qui concerne le nombre d'entrées. Puis les progrès de cette limite, avec un degré de corrélation avec le nombre de lignes dans le tableau à mesure qu'il grandit. Exemple, c'est quand il n'y a pas beaucoup d'entrées. Disons que vous disposez de 3. Sans limite sur le nombre aléatoire, vous pouvez avoir 2 très petit nombre et une grande. Le plus petit des 3 ne sera presque jamais être appelé lorsque l'écart entre le min, lui-même, et le nombre du milieu est si petit. Que faire si min=0, max=100 avec 3 entrées & rand #'s assigné était de 49, 50, 51?
Je ne le comprends pas. Comment est-ce différent de juste sélectionnant aléatoirement un nombre entre 1 et max(id) et de choisir l'entrée avec une pièce d'identité? Pourquoi avez-vous besoin d'une colonne supplémentaire?
OriginalL'auteur CesarB
Voici une solution qui fonctionne assez rapidement, et on obtient une meilleure distribution aléatoire sans en fonction des valeurs d'id d'être contigus ou en commençant à 1.
$query
égale à la ci-dessus et ensuite de faire l'habitudemysql_query($query)
ne retourne pas de résultat. Merci.C'est de 1,5 analyses de la table -- 1 pour le
COUNT(*)
(en supposant que InnoDB), quelque chose de moins qu'une analyse complète de laOFFSET @r
. Mais il est excellent à être aléatoire et non pas en fonction des propriétés d'une pièce d'identité.La droite. Une autre solution serait d'énumérer les lignes avec une nouvelle colonne est remplie avec la série des nombres entiers. Ensuite, on peut obtenir la plus grande avec MAX() au lieu de COUNT(), puis sélectionnez-le en un indice sans faire face à des lacunes. Bien que cette solution nécessite la renumérotation des lignes aller et venir.
OriginalL'auteur Bill Karwin
Peut-être que vous pourriez faire quelque chose comme:
C'est en supposant que vos numéros d'identification sont tous séquentielles sans lacunes.
Qui suppose que l'expression est mise en cache et de ne pas recalculée pour chaque ligne.
Il y a des lacunes dans la clé primaire, comme certaines lignes sont supprimés.
OriginalL'auteur davr
Ajouter une colonne contenant un calculés valeur aléatoire à chaque ligne, et de l'utiliser dans la commande de la clause, en limitant à un résultat au moment de la sélection. Cela fonctionne plus rapidement que d'avoir la table d'analyse que
ORDER BY RANDOM()
causes.Mise à jour: Vous avez encore besoin de calculer certains aléatoire de la valeur avant l'émission de la
SELECT
déclaration lors de la récupération, bien sûr, par exemple,Comment se fait-c'est -2, encore Cesar B est +17? Ils semblent à peu près la même chose pour moi.
Devrait-il être "SELECT * from
foo
OÙfoo_rand
>= {certaine valeur aléatoire} COMMANDE PAR foo_rand LIMITE de 1"?Que faire si votre {certaine valeur aléatoire} est supérieur au plus élevé de pré-générés de manière aléatoire dans le tableau. Vous reviendrez un jeu d'enregistrements vide.
OriginalL'auteur Rob
Un facile, mais de façon lente (bon pour de petits tableaux)
Vrai. C'est rapide en temps de développement. (et en temps de réponse 🙂 ). Je vais le laisser ici pour les non grande table utilisateurs qui pourraient en avoir besoin
"petit" peut être étonnamment petit (j'ai couru dans des problèmes avec une 20k entrée de la table sur un hôte virtuel), et le suivi de ce type de problème peut être un royal de la douleur dans le dos. Faites-vous une faveur et à l'utilisation d'un algorithme approprié dès le début.
Cela va provoquer une grande performance de drain pour les grandes tables. Cochez cette question semblable stackoverflow.com/questions/1244555/...
OriginalL'auteur Vinko Vrsalovic
En pseudo code:
Cela suppose que
id
est unique (primaire).Que faire si il y a un milliard de lignes? Cela signifie que votre liste de variable est énorme.
OriginalL'auteur Anders Sandvig
Il y a un autre moyen de produire de l'aléatoire des lignes à l'aide seulement d'une requête et sans order by rand().
Il implique des Variables Définies par l'Utilisateur.
Voir comment produire des lignes aléatoires à partir d'une table
OriginalL'auteur Ilan Hazan
Afin de trouver des lignes aléatoires à partir d'une table, ne pas utiliser ORDER BY RAND() car les forces de MySQL pour faire un fichier de tri et seulement ensuite pour récupérer la limite de nombre de lignes nécessaires. Afin d'éviter ce fichier complet trier, utiliser la fonction RAND() seulement à la clause where. Il s'arrêtera dès qu'il atteint le nombre requis de lignes.
Voir
http://www.rndblog.com/how-to-select-random-rows-in-mysql/
OriginalL'auteur Sagi Bron
si vous n'avez pas supprimer la ligne dans cette table, le moyen le plus efficace est:
(si vous connaissez les faibles id de l'ignorer)
OriginalL'auteur parm.95
Pour la sélection de plusieurs lignes aléatoires à partir d'une table donnée (disons "mots"), notre équipe est venu avec cette beauté:
OriginalL'auteur
Le classique "SELECT id from table ORDER BY RAND() LIMIT 1" est en fait OK.
Voir la suite de l'extrait de manuel MySQL:
Si vous utilisez LIMITE row_count avec COMMANDE PAR, MySQL se termine le tri dès qu'il a trouvé le premier row_count lignes du résultat trié, plutôt que de trier le résultat entier.
il y a encore de problème de performance, je suppose que c'est pas OK
OriginalL'auteur igelkott
Avec un ordre yo va faire un balayage complet de la table.
Son meilleur si vous faites un select count(*) et, plus tard, d'obtenir une ligne aléatoire=rownum entre 0 et le dernier registre
OriginalL'auteur MazarD
Prendre un coup d'oeil à ce lien par Jan Kneschke ou cette SORTE de réponse comme ils ont tous les deux discuter de la même question. La DONC réponse va sur les différentes options et a quelques bonnes suggestions en fonction de vos besoins. Jan va sur toutes les différentes options et les caractéristiques de performance de chacun. Il se termine avec le suivant pour la méthode la plus optimisée pour ce faire, au sein d'une base MySQL sélectionnez:
HTH,
-Dipin
OriginalL'auteur Dipin
Je suis un peu nouveau pour SQL mais comment sur la génération d'un nombre aléatoire en PHP et utilisant
cela ne résout pas le problème avec les trous de la table.
Mais voici une torsion sur lassevks suggestion:
Utiliser mysql_num_rows() en PHP créer un nombre aléatoire basé sur le résultat ci-dessus:
Sur une note de côté, juste la lenteur est
SELECT * FROM the_table
:La création d'un nombre aléatoire basé sur
mysql_num_rows()
, puis en déplaçant le pointeur de données à ce pointmysql_data_seek()
. Juste comment ralentir ce que ce sera sur les grandes tables à dire un million de lignes?OriginalL'auteur
Je suis tombé sur le problème où mon Id n'étaient pas séquentielle. Ce que je suis venu avec cette.
Le nombre de lignes retournées sont environ 5, mais je me limite à 1.
Si vous souhaitez ajouter une autre clause where, il devient un peu plus intéressant. Dites que vous voulez rechercher des produits sur les rabais.
Ce que vous avez à faire est de vous assurer que vous êtes de retour assez conséquent et c'est pourquoi je l'ai mis à 100. Avoir une remise<.2 clause dans la sous-requête est 10x plus lent, il est donc préférable de revenir plus les résultats et la limite.
OriginalL'auteur bikedorkseattle
Je vois ici beaucoup de solution. Un ou deux semble ok, mais les autres solutions ont certaines contraintes. Mais la suite de la solution pour l'ensemble de la situation
Ici, l'id n'a pas besoin d'être séquentielle. Il pourrait être une clé primaire/unique/auto incrémentée. Veuillez voir la suite Moyen le plus rapide pour sélectionner une ligne au hasard à partir d'une grande table MySQL
Merci
Zillur
- http://www.techinfobest.com
OriginalL'auteur Zillur
Utiliser la sous requête pour obtenir la ligne aléatoire
OriginalL'auteur MANOJ
Dans mon cas, ma table a un id comme clé primaire auto-incrémentée avec pas de lacunes, de sorte que je peux utiliser
COUNT(*)
ouMAX(id)
pour obtenir le nombre de lignes.J'ai fait ce script pour tester la manière la plus rapide de l'opération:
Les résultats sont les suivants:
36.8418693542479 ms
0.241041183472 ms
0.216960906982 ms
Réponse avec la méthode de l'ordre:
OriginalL'auteur Toni Almeida
J'ai utilisé cette et le travail a été fait
la référence de ici
OriginalL'auteur Yousef Altaf
Créer une Fonction pour ce faire probablement la meilleure réponse et la plus rapide de réponse ici!
Pros - Fonctionne même avec des Lacunes et extrêmement rapide.
Veuillez garder à l'esprit ce code n'a pas été testé, mais est un concept de travail à rendement aléatoire des entrées, même avec des lacunes.. tant Que les écarts ne sont pas énormes assez pour causer un temps de chargement de la question.
OriginalL'auteur RandomGuest
Rapide et sale méthode:
La complexité de la première requête est O(1) pour les tables MyISAM.
La deuxième requête s'accompagne d'un tableau de l'analyse complète. Complexité = O(n)
Sale et méthode rapide:
Garder une table séparée pour cette seule fin. Vous devez également insérer les mêmes lignes de ce tableau à chaque fois que l'insertion de la table d'origine. Hypothèse: Pas De Suppressions.
Si les Suppressions sont autorisés,
La complexité est O(1).
OriginalL'auteur yogman
SELECT DISTINCT * FROM yourTable WHERE 4 = 4 LIMIT 1;
OriginalL'auteur proggL