Question

Je sais que si je gère cette requête

select top 100 * from mytable order by newid()

Il obtiendra 100 enregistrements aléatoires de ma table.

Cependant, je suis un peu confus quant à la façon dont cela fonctionne, car je ne vois pas newid() dans le select liste. Quelqu'un peut-il expliquer? Y a-t-il quelque chose de spécial newid() ici?

Était-ce utile?

La solution

Je sais ce que fait NewId (), j'essaie juste de comprendre comment cela aiderait dans la sélection aléatoire. Est-ce que (1) l'instruction SELECT sélectionnera tout parmi MyTable, (2) pour chaque ligne sélectionnée, cognez-vous sur un identifiant unique généré par NewId (), (3) Triez les lignes par cet identifiant unique et (4) choisissez le haut 100 de la liste triée?

Oui. C'est à peu près exactement correct (sauf qu'il n'a pas nécessairement besoin de trier tout les lignes). Vous pouvez le vérifier en examinant le plan d'exécution réel.

SELECT TOP 100 * 
FROM master..spt_values 
ORDER BY NEWID()

L'opérateur scalaire de calcul ajoute le NEWID() Colonne sur chaque ligne (2506 dans le tableau dans mon exemple de requête) puis les lignes du tableau sont triées par cette colonne avec le top 100 sélectionné.

SQL Server n'a pas vraiment besoin de trier l'ensemble entier à partir de positions 100, il utilise donc un TOP N Opérateur de tri qui tente d'effectuer l'ensemble de l'opération de tri en mémoire (pour de petites valeurs de N)

Plan

Autres conseils

En général, cela fonctionne comme ceci:

  • Toutes les lignes de ma table est "boucle"
  • NewId () est exécuté pour chaque ligne
  • Les lignes sont triées en fonction du nombre aléatoire de NewId ()
  • 100 premières lignes sont sélectionnées

La clé ici est la fonction NewID, qui génère un identifiant unique (GUID) à l'échelle mondiale en mémoire pour chaque ligne. Par définition, le GUID est unique et assez aléatoire; Ainsi, lorsque vous triez par ce GUID avec la clause Order By, vous obtenez une commande aléatoire des lignes dans le tableau. Prendre les 10% les plus élevés (ou tout pourcentage que vous voulez) vous donnera un échantillonnage aléatoire des lignes dans le tableau.

Une requête NewID est proposée; Il est simple et fonctionne très bien pour les petites tables. Cependant, la requête NewID a un gros inconvénient lorsque vous l'utilisez pour les grandes tables. La clause Order by fait copier toutes les lignes du tableau dans la base de données TempDB, où elles sont triées. Cela provoque deux problèmes: l'opération de tri a généralement un coût élevé qui lui est associé. Le tri peut utiliser beaucoup d'E / S disque et peut fonctionner longtemps. Dans le pire des cas, TempDB peut manquer d'espace. Dans le meilleur des cas, TempDB peut occuper une grande quantité d'espace disque qui ne sera jamais récupéré sans une commande de rétrécissement manuelle. Ce dont vous avez besoin est un moyen de sélectionner les lignes au hasard qui n'utilisera pas TempDB et ne deviendra pas beaucoup plus lente à mesure que le tableau s'agrandit. Voici une nouvelle idée sur la façon de procéder:

SELECT * FROM master..spt_values
  WHERE (ABS(CAST(
  (BINARY_CHECKSUM(*) *
  RAND()) as int)) % 100) < 10

L'idée de base derrière cette requête est que nous voulons générer un nombre aléatoire entre 0 et 99 pour chaque ligne du tableau, puis choisir toutes ces lignes dont le nombre aléatoire est inférieur à la valeur du pourcentage spécifié. Dans cet exemple, nous voulons environ 10% des lignes sélectionnées au hasard; Par conséquent, nous choisissons toutes les lignes dont le nombre aléatoire est inférieur à 10.

comme MSDN dit:

NewId () crée une valeur unique de type identifiant unique.

Et votre table sera triée par ces valeurs aléatoires.

utilisation select top 100 randid = newid(), * from mytable order by randidVous serez clarifié alors ..

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top