Performance de requête Django

J'ai une question relative aux performances concernant les requêtes django.

Dis que j'ai une table d'employés avec 10 000 loggings. Maintenant Si je cherche à sélectionner 5 employés au hasard dont l'âge est supérieur ou égal à 20, disons que 5 500 employés ont 20 ans ou plus. La requête django serait:

Employee.objects.filter(age__gte=20).order_by('?')[:5] 

et la contrepartie brute de cette requête dans mysql sera:

 SELECT * FROM `database`.`employee` WHERE `employee`.`age` >= 20 ORDER BY RAND () LIMIT 5; 

À partir de l'apparence de la requête django, la database renvoie d'abord les 5 500 loggings, puis python sortinge ces loggings sur un ordre random ou quel que soit l'ordre choisi et un bloc de cinq premiers loggings est renvoyé alors que la requête brute renvoie directement cinq loggings de la database.

Ma question est la suivante: y a-t-il une différence de performance entre les deux requêtes? Si oui lequel est le meilleur et pourquoi?

J'ai fait une vérification rapide de mon projet existant:

 queryset = BlahModel.objects.order_by('?')[:5] print queryset.query 

Le résultat est:

 SELECT `blah_model`.`id`, `blah_model`.`date` FROM `blah_model` ORDER BY RAND() LIMIT 5; 

Donc, ils sont les mêmes.

Je ne serais pas trop surpris du résultat, car ORM de django est un mappage direct entre le résultat de la requête sql et l'object django, donc order_by('?') Serait égal à ORDER BY RAND() , même l'instruction [:5] est traduit en LIMIT dans mysql (voici le doc et doc ).

Tout problème de performances que vous voyez n'est pas dû à django. Comme Shang Wang l'a déjà souligné, la requête exécutée par Django est exactement la même que la requête brute. Le problème est avec l'appel de rand ().

Comme cela a été expliqué ailleurs, y compris certaines réponses StackOveflow comme celui-ci: https://stackoverflow.com/a/6911022/267540 problème est causé par le fait qu'une valeur random doit être calculée pour chaque ligne. Heureusement, vous avez une clause WHERE qui réduit le nombre de lignes. BUt à mesure que datatables augmentent, votre requête deviendra progressivement plus lente et plus lente.

Ce lien a plusieurs suggestions différentes sur la façon de surmonter ce problème http://www.warpconduit.net/2011/03/23/selecting-a-random-record-using-mysql-benchmark-results/