无图无真相,先上图,这是读django queryset文档的时候,文档上的一段note
当时读完这句,就是觉得说在mysql上对于__in的使用,需要把__in中的条件拆分成两句写,也没特别在意,之后的代码也是常常这么写,没察觉什么不对劲,虽然我们也是用mysql
Model.objects.filter(xx__in=queryset)
近期有客户反映,某个功能反映有点慢,我试了试,一个查询20w行左右的sql需要大约5s,这确实太慢了,定位到这句查询语句后,查看对应的sql,发现用了子查询,难怪那么慢,想起文档上的那个note(上图),然后改成
Model.objects.filter(xx__in=list(queryset.values_list('id',flat=True)))
Oh,sql的执行时间在200ms左右,看来文档说的还是很有道理的。
PS:两种结果转化为sql对比
#Model.objects.filter(xx__in=queryset) 实际执行的sql是
select ... where id in (select id from ...)
#Model.objects.filter(xx__in=list(queryset.values_list('id',flat=True)))实际执行的sql是
select ... where id in (1,2,3)