zoukankan      html  css  js  c++  java
  • Django——select_related和prefetch_related的使用与性能测试

    MessageModel.objects.select_related('sender').query.__str__()
    Out[6]: 'SELECT "tb_message.all_fields", "tb_users.all_fields", FROM "tb_message" INNER JOIN "tb_users" ON ("tb_message"."sender_id" = "tb_users"."id")'
    
    MessageModel.objects.all().query.__str__()
    Out[7]: 'SELECT "tb_message.all_fields" FROM "tb_message"'
    

    测试

    @timer
    def gao_ji_search():
        data = []
        datas = MessageModel.objects.select_related('sender')  # ForeignKey字段
        for i in datas:
            data.append(i.sender.username)
        return any(data)
    
    @timer
    def di_ji_search():
        data = []
        datas = MessageModel.objects.all()
        for i in datas:
            data.append(i.sender.username)
        return any(data)
    
    MessageModel.objects.count()
    Out[47]: 9
    
    gao_ji_search()
    <gao_ji_search>运行用时0.011433839797973633s
    Out[4]: True
      
    di_ji_search()
    <di_ji_search>运行用时0.11970925331115723s
    Out[3]: True
    

    结论:select_related对于o2o和m2o字段,可以牺牲内存优化对数据库的操作次数,较少时间的消耗


    使用prefetch_related方法和不使用

    [i.cargo_price_orders.all().values('code').query.__str__() for i in CargoModel.objects.all()[1:2]]
    Out[25]: ['SELECT "tb_price_order"."code" FROM "tb_price_order" INNER JOIN "tb_price_order_cargo_ref" ON ("tb_price_order"."id" = "tb_price_order_cargo_ref"."priceordermodel_id") WHERE "tb_price_order_cargo_ref"."cargomodel_id" = 11']
    
    [i.cargo_price_orders.all().values('code').query.__str__() for i in CargoModel.objects.prefetch_related('cargo_price_orders')[1:2]]
    Out[39]: ['SELECT "tb_price_order"."code" FROM "tb_price_order" INNER JOIN "tb_price_order_cargo_ref" ON ("tb_price_order"."id" = "tb_price_order_cargo_ref"."priceordermodel_id") WHERE "tb_price_order_cargo_ref"."cargomodel_id" = 11']
    

    没啥区别,于是看了一下查询结果带有哪些参数,找到了一个self._prefetch_related_lookups,记录预存储的m2m字段,一个self._prefetch_done,布尔值,调用了prefetch_related方法的结果里面值都是对应的有结果:

    _prefetch_related_lookups = ('cargo_price_orders',)
    _prefetch_done = True
    

    所以可以推测,预存储的数据,之后再使用,是不需要在进行sql查询的

    测试

    @timer
    def gao_ji_search():
        data = []
        # ManyToManyField字段反向查找的字段
        datas = CargoModel.objects.prefetch_related('cargo_price_orders')  
        for i in datas:
            for j in i.cargo_price_orders.all():
                data.append(j.code)
        return any(data)
    
    @timer
    def di_ji_search():
        data = []
        datas = CargoModel.objects.all()
        for i in datas:
            for j in i.cargo_price_orders.all():
                data.append(j.code)
        return any(data)
    
    CargoModel.objects.count()
    Out[6]: 21185
      
    di_ji_search()
    <di_ji_search>运行用时31.286818027496338s
    Out[3]: True
      
    gao_ji_search()
    <gao_ji_search>运行用时3.2482240200042725s
    Out[4]: True
    

    结论:prefetch_related对于m2m字段,可以牺牲内存优化对数据库的操作次数,较少时间的消耗

  • 相关阅读:
    代理模式之动态代理
    代理模式之静态代理
    基于Java类进行配置Spring
    Spring使用注解开发
    Spring的自动装配
    Bean的作用域
    Spring配置
    最全总结 | 聊聊 Python 办公自动化之 Excel(上)
    最全总结 | 聊聊 Python 数据处理全家桶(MongoDB 篇)
    最全总结 | 聊聊 Python 数据处理全家桶(Redis篇)
  • 原文地址:https://www.cnblogs.com/pywjh/p/14803197.html
Copyright © 2011-2022 走看看