5 votes

100k Rows retournés dans un ordre aléatoire, sans time out SQL s'il vous plaît

Ok,

J'ai beaucoup lu sur le retour d'un ensemble de rangées aléatoires l'année dernière, et la solution que nous avons trouvée est la suivante

ORDER BY newid()

Cela convient pour les rangs de moins de 5 000. Mais lorsque nous obtenons >10-20k lignes, nous obtenons des time outs SQL, l'exécution planifiée me dit que 76% du coût de ma requête provient de cette ligne. et la suppression de cette ligne augmente la vitesse d'un ordre de grandeur lorsque nous avons une grande quantité de lignes.

Nos utilisateurs ont besoin de traiter jusqu'à 100 000 lignes à la fois de cette manière.

Pour vous donner un peu plus de détails.

Nous disposons d'un tableau contenant 2,6 millions de codes alphanumériques à 4 chiffres. Nous utilisons un ensemble aléatoire de ces codes pour entrer dans un lieu. Par exemple, si nous organisons un événement d'une capacité de 5 000 personnes, un ensemble aléatoire de 5 000 de ces codes sera tiré de la table et remis à chaque client sous forme de code-barres, puis l'application de lecture de codes-barres à l'entrée aura la même liste de 5 000. La raison de l'utilisation d'un code alphanumérique à 4 chiffres (et non d'un numéro stupidement long comme un GUID) est qu'il est facile pour les gens de noter le numéro (ou de l'envoyer par SMS à un ami) et de l'apporter pour le faire entrer manuellement, donc nous ne voulons pas d'une grande quantité de caractères. Les clients adorent la dernière partie.

Y a-t-il un meilleur moyen que ORDER BY newid() ou existe-t-il un moyen plus rapide d'obtenir 100 000 lignes aléatoires à partir d'une table de 2,6 millions de lignes ?

Oh, et nous utilisons MS SQL 2005.

Merci,

Jo

7voto

adrianbanks Points 36858

Il existe un article de MSDN intitulé " Sélection aléatoire de rangées dans un grand tableau "qui traite de ce problème exact et présente une solution (sans tri, mais en utilisant une clause WHERE sur une colonne générée pour filtrer les lignes).

La raison de la lenteur de votre requête est que la ORDER BY fait en sorte que la table entière soit copiée dans tempdb pour être triée.

3voto

Anon. Points 26829

Si vous voulez générer des codes aléatoires à 4 chiffres, pourquoi ne pas les générer au lieu d'essayer de les extraire d'une base de données ?

Générez 100 000 numéros uniques de 0 à 1 679 616 (qui est le nombre de codes alphanumériques uniques à quatre chiffres, en ignorant la casse - 2,6 millions de lignes doivent avoir quelques doublons) et convertissez-les en vos codes à quatre chiffres.

1voto

user76035 Points 1169

Vous n'avez pas besoin de trier.

 DECLARE @RandomNumber int
 DECLARE @Threshold float
 SELECT @RandomNumber = COUNT(*) FROM customers
 SELECT @Threshold = 50000 / @RandomNumber

 SELECT TOP 50000 * FROM customers WHERE rand() > @Threshold ORDER BY newid()

0voto

Mitch Wheat Points 169614

Juste à titre d'information, quelles sont les performances si vous remplacez la carte de crédit par une autre carte de crédit ?

ORDER BY newid()

par

ORDER BY CHECKSUM(newid())

0voto

Bentley Davis Points 349

Une solution consiste à décomposer le processus en plusieurs étapes. Ajouter une colonne dans la table pour un GUID, puis effectuer une mise à jour de la table en ajoutant les GUID. Cela peut être fait à l'avance si nécessaire. Vous devriez alors être en mesure d'exécuter la requête avec un orderby sur la colonne GUID pour recevoir les résultats de la même manière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X