前言
博主目前接手了一个项目,该项目代码从某马微店那里买来,社交金融相关。这个项目的代码可以说是逻辑混乱,毫无可重用性,而且又无文档,git message中一堆毫无用处的“update”,PEP8规范?不存在的。使得我每日游走在被代码劝退的边缘。
震惊!一次请求1W多条sql。
该功能为商品的热销分类表单。之前大概看了一眼,数据是先从redis中取,redis值存的永久有效,没有的话查DB。然后某天清了一下测试数据库的redis,这下好了,接口超时。查了一下silk发现运行了1w多次sql。
万恶之源的代码,难怪查了1W多次,这外键coupon,每次都要查询数据库。而且这里channel也没有用set,这简直基础数据结构都没掌握啊。
1 | tbkcoupons = TbkCouponTags.objects.filter(is_hot=True) |
使用select_related简单的处理了一下
1 | tbkcoupons = TbkCouponTags.objects.select_related('coupon').filter(is_hot=True) |
快了10倍,冷静一下,思考一下这大哥到底要干嘛,后面看到拿到了tbkcoupons
没有再做其他用处。所以这东西完全可以使用反向连接加去重来解决啊,看来sql基础也欠缺。这里改成了values+distinct来处理,因为mysql不支持distinct(‘channel’)这种指定字段的形式。
1 | tbkcoupons = TbkCoupon.objects.filter(tbkcoupontags__is_hot=True).values('channel').distinct() |
后面的逻辑判断,又使用了一堆的ifelse
,看着不清晰,将其改为了字典。这些倒不是什么大问题。
最后,修改了一些取值的逻辑。最后将结果保存到了redis中。命中缓存的话大概10+ms。
后来又发现了一个有意思的事情,他好像也知道这个查询挺慢的,所以用celerybeat实现了一个周期任务,定时地更新这个redis。
返回按照当前查询数组顺序的queryset。
遇见了这样一个需求 ,收藏列表需要返回按照收藏顺序的商品。而这个顺序保存在java后台。通过Thrift接口调用,返回了一个id列表,而商品保存在我这里。需要根据这个id的顺序返回queryset。django-get-a-queryset-from-array-of-ids-in-specific-order。
1 | from django.db.models import Case, When |