無圖無真相,先上圖,這是讀django queryset文檔的時候,文檔上的一段note

圖片.png
當時讀完這句,就是覺得說在mysql上對于__in的使用,需要把__in中的條件拆分成兩句寫,也沒特別在意,之后的代碼也是常常這么寫,沒察覺什么不對勁,雖然我們也是用mysql
Model.objects.filter(xx__in=queryset)
近期有客戶反映,某個功能反映有點慢,我試了試,一個查詢20w行左右的sql需要大約5s,這確實太慢了,定位到這句查詢語句后,查看對應的sql,發(fā)現(xiàn)用了子查詢,難怪那么慢,想起文檔上的那個note(上圖),然后改成
Model.objects.filter(xx__in=list(queryset.values_list('id',flat=True)))
Oh,sql的執(zhí)行時間在200ms左右,看來文檔說的還是很有道理的。
PS:兩種結果轉化為sql對比
#Model.objects.filter(xx__in=queryset) 實際執(zhí)行的sql是
select ... where id in (select id from ...)
#Model.objects.filter(xx__in=list(queryset.values_list('id',flat=True)))實際執(zhí)行的sql是
select ... where id in (1,2,3)