python django响应时间长但不知道怎么回事

Posted

技术标签:

【中文标题】python django响应时间长但不知道怎么回事【英文标题】:python django response time long but don't know what's wrong 【发布时间】:2018-04-19 14:31:18 【问题描述】:

我的 django 应用使用 django-rest-framework 和 mysql。 我测试了我的应用程序,但几乎所有功能的响应时间都很长。不知道是什么问题。

这是响应时间最长的函数之一。

   180232 function calls (171585 primitive calls) in 1.110 seconds

   Ordered by: internal time
   List reduced from 757 to 151 due to restriction <0.2>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      105    0.597    0.006    0.597    0.006 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:268(query)
        2    0.154    0.077    0.174    0.087 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:81(__init__)
        4    0.020    0.005    0.020    0.005 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:254(autocommit)
8800/3582    0.010    0.000    0.828    0.000 built-in method builtins.getattr
    20156    0.010    0.000    0.022    0.000 built-in method builtins.isinstance
  200/100    0.009    0.000    0.886    0.009 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/rest_framework/serializers.py:479(to_representation)
        2    0.009    0.005    0.009    0.005 function Connection.set_character_set at 0x109b506a8
     6920    0.009    0.000    0.009    0.000 built-in method builtins.hasattr
                                      ....

这个函数是列表的第一页,总数为1000,页面大小为100。每条记录只连接一个表。查询花了很长时间,所以我将 Django ORM 更改为 Raw Query,但时间是一样的。 (也许我使用了错误的原始查询)

验证验证响应时间长

        2199 function calls (2133 primitive calls) in 0.195 seconds

   Ordered by: internal time
   List reduced from 419 to 84 due to restriction <0.2>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        2    0.153    0.076    0.169    0.084 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:81(__init__)
        4    0.016    0.004    0.016    0.004 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:254(autocommit)
        3    0.014    0.005    0.014    0.005 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:268(query)
        2    0.008    0.004    0.008    0.004 function Connection.set_character_set at 0x109b506a8

我认为它必须少于 60 毫秒。 (也许我的想法是错误的)

是 django 查询太慢还是我的应用程序有问题?我知道是什么问题。

DEBUGFalsesettings 它只是本地runserver 未部署。但部署时的响应时间几乎相同(部署速度更快,但查询时间相同) 抱歉信息不佳。我的网络开发经验只有半年。如果您想要更多,我会尝试。

编辑 查看代码

class OrderListCreationAPI(generics.ListCreateAPIView):
    permission_classes = (
        permissions.IsAuthenticatedOrReadOnly,
        IsAdminOrClient,
    )
    pagination_class = StandardListPagination


    def get_queryset(self):
        if self.request.method == 'GET':
            queryset = CacheOrderList.objects.all()
            return queryset
        else:
            return Order.objects.all()

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return CacheOrderListSerializer
        else:
            return OrderSerializer

序列化代码

class CacheOrderListSerializer(serializers.ModelSerializer):
    base = CacheBaseSerializer(read_only=True)

    class Meta:
        model = CacheOrderList
        fields = '__all__'

型号代码

class CacheBase(models.Model):
    created_time = models.DateTimeField(auto_now_add=True)
    order = models.OneToOneField('order.Order', on_delete=models.CASCADE, related_name='cache', primary_key=True)
    driver_user = models.ForeignKey('member.DriverUser', on_delete=models.SET_NULL, null=True)
    client_name = models.CharField(max_length=20, null=True)
    load_address = models.CharField(max_length=45, null=True)
    load_company = models.CharField(max_length=20, null=True)
    load_date = models.DateField(null=True)
    load_time = models.CharField(max_length=30)
    unload_address = models.CharField(max_length=45, null=True)
    unload_company = models.CharField(max_length=20, null=True)
    unload_date = models.DateField(null=True)
    unload_time = models.CharField(max_length=30)
    stop_count = models.IntegerField(default=0)
    is_round = models.BooleanField(default=False)
    is_mix = models.BooleanField(default=False)
    car_ton = models.CharField(max_length=15, null=True)
    weight = models.FloatField(null=True)
    payment_method = models.BooleanField(default=s.ORDER_PAYMENT_METHOD_ADVANCE)
    contract_fee = models.IntegerField(null=True)
    driver_fee = models.IntegerField(null=True)
    order_fee = models.IntegerField(null=True)
    is_deleted = models.BooleanField(default=False)


class CacheOrderList(models.Model):
    base = models.OneToOneField(CacheBase, on_delete=models.CASCADE, related_name='order_list')
    order_status = models.IntegerField(null=True)
    order_created_time = models.DateTimeField(null=True)
    car_type = models.CharField(max_length=10, null=True)
    asignee = models.CharField(max_length=20, null=True)
    objects = CacheManager()

    class Meta:
        ordering = ('-order_created_time',)
        db_table = 'CacheOrderList'

EDIT2 在列表功能中,app 已经获得了 100 个项目,但之后,app 再次查询 1 per 1。不使用已经获得的项目。所以每个查询花费了 100 * 的时间。

这可能是因为序列化程序没有使用分页获得的记录。所以分页 2 查询 + 序列化程序 100 查询 + 其他。

我不知道为什么会这样。

【问题讨论】:

你有多少行?你试过直接在mysql中执行同样的查询吗? 大约 1000。我确实在 mysql 中执行。耗时不到 60 毫秒。我更改了代码以在我的应用程序中使用原始查询(相同的查询)。但时间与我的帖子结果相同。 你能把代码也贴出来吗? 编辑完成。只是简单的列表代码。 使用 django-debug-toolbar 检查问题出在哪里。 【参考方案1】:

在基本字段的 CacheOrderList 查询集中使用 select_related。这将使用您在方法中提供的外键关联准备一个查询集缓存,基本上不会一次又一次地访问数据库。

示例

def get_queryset(self):
    if self.request.method == 'GET':
        # prepare related models cache using `select_related`
        queryset = CacheOrderList.objects.all().select_related('base')
        return queryset
    else:
        return Order.objects.all()

【讨论】:

谢谢。我看到了这个帖子。 ses4j.github.io/2015/11/23/…

以上是关于python django响应时间长但不知道怎么回事的主要内容,如果未能解决你的问题,请参考以下文章

Django 事务回滚 HTTP 错误响应

使用 json 在 python / django 中设置用户登录,但不知道从哪里开始

Django - 重定向回页面显示http响应(Json数据)而不是呈现

django 编辑表单,数据怎么回显呀

数据当用户在验证失败(Python,Django)时被重定向回表单时如何保留表单?

如何在 Django REST Swagger 中生成响应消息列表?