Hi, Here are some performance numbers against a local SQLite in case any one is interested. GL has about 40,000 records for reference.324 was just a random number chosen, of different 'in's
>>> sys.version'3.7.2rc1 (default, Dec 12 2018, 06:25:49) \n[GCC 8.2.0]'>>> django.__version__'3.0.6'>>> import myapp.models as m>>> x = m.GL.objects.all()[324]>>> x in m.GL.objects.all()True >>> import timeit>>> timeit.timeit('m.GL.objects.filter(pk=x.pk)', setup='import myapp.models as m;x = m.GL.objects.all()[324]', number=100)0.05818330496549606>>> timeit.timeit('x in qs', setup='import myapp.models as m;qs = m.GL.objects.all(); x=qs[324]', number=100)1.5688817161135375 On Tue, 2020-06-02 at 05:53 -0700, Tim Graham wrote: > It may help to know that QuerySet.__contains__() was implemented > until Django 1.6 when chunked reads were removed from QuerySet > iteration: > > https://github.com/django/django/commit/70679243d1786e03557c28929f9762a119e3ac14 > On Tuesday, June 2, 2020 at 7:43:25 AM UTC-4, Aymeric Augustin wrote: > > > On 2 Jun 2020, at 13:30, Florian Apolloner <f.apo...@gmail.com> > > > wrote: > > > > > > On Tuesday, June 2, 2020 at 11:28:34 AM UTC+2, Adam Johnson > > > wrote: > > > > > If you already fetched the queryset, `if obj in queryset` > > > > > will make a new database query > > > > > > > > I don't see why we couldn't implement __contains__ to do a walk > > > > through _result_cache if it has been fetched? > > > > > > > > > > we are doing the same for len() IIRC. I have to say it sometimes > > > makes it a little bit hard to debug, but if it is documented as > > > such it should be okay. > > > > These are good points. > > > > As far as I can tell, the current implementation of __len__ is to > > fetch the whole queryset: > > > > def __len__(self): > > self._fetch_all() > > return len(self._result_cache) > > > > I'm almost sure doing an automatic .count() was discussed in the > > past. I don't remember why we rejected it — perhaps because in most > > cases, when you need the length of a queryset, you will also > > iterate it? > > > > The suggestion for __contains__ is similar: doing an automatic > > .filter(pk=obj.pk).exists(). We could do it only if the queryset > > isn't fetched yet, but I'm afraid this may be too magical. Is it > > reasonable to have `total = len(queryset); found = obj in queryset` > > make one SQL query while `found = obj in queryset; total = > > len(queryset)` makes two queries? > > > > Now I'm worried that we may be making inconsistent decisions > > between __len__ and __contains__... Let's make sure we're > > consistent across dunder methods. > > > > -- > > Aymeric > > > > > > > > -- > > You received this message because you are subscribed to the Google > Groups "Django developers (Contributions to Django itself)" group. > > To unsubscribe from this group and stop receiving emails from it, > send an email to django-developers+unsubscr...@googlegroups.com. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/django-developers/55b4d7e0-ba30-48b2-8005-d27adacc7fd0%40googlegroups.com > . > -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/69fdfe26be34d37a09cfe9dc7f5cc9a4c580d1d9.camel%40gammascience.co.uk.