You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django 4异步查询为何未比同步查询提升性能?

问题描述

我正在开展一项测试,评估升级至Django 4并将部分查询集改为异步的价值。为了测试性能,我编写了同步与异步两类视图,但在数据库交互环节未发现性能提升。我特意编写了两个低效视图来测试数据库压力:

同步视图

def some_validation(post):
    """Check that number of tags > 5"""
    return post.tags.count() > 5


@api_view(["GET"])
def posts_with_tags(request):
    start_time = time.monotonic()
    posts = []
    for post in Post.objects.all():
        tags = []
        for tag in post.tags.all():
            tags.append(tag.name)
        post_data = {
            "id": post.id,
            "title": post.title,
            "content": post.content,
            "tags": tags,
            "validation_passed": some_validation(post),
        }
        posts.append(post_data)
    end_time = time.monotonic()
    time_elapsed = end_time - start_time
    return Response(
        {
            "posts": posts,
            "time_elapsed": time_elapsed,
            "num_queries": len(connection.queries),
        }
    )

异步视图

async def some_validation_async(post):
    """Check that number of tags > 5"""
    return await post.tags.acount() > 5


@api_view(["GET"])
async def posts_with_tags_async(request):
    start_time = time.monotonic()

    post_data = []

    async for post in Post.objects.all():
        post_tags = []
        async for tag in post.tags.all():
            post_tags.append(tag.name)

        validation_res = await some_validation_async(post)

        post_data.append(
            {
                "id": post.id,
                "title": post.title,
                "content": post.content,
                "tags": post_tags,
                "validation_passed": validation_res,
            }
        )

    end_time = time.monotonic()
    time_elapsed = end_time - start_time

    return Response(
        {
            "posts": post_data,
            "time_elapsed": time_elapsed,
            "num_queries": len(connection.queries),
        }
    )

类似地,我还创建了用于写入和删除数据的视图,但所有异步查询集交互场景均未出现性能提升,想请教可能忽略了哪些因素?


可能忽略的因素
  • 异步代码未实现真正并行:你的异步视图采用async for逐个遍历Post,每个Post的标签查询、验证操作都是串行执行,逻辑和同步版本本质一致。异步的核心优势是并行处理IO任务,需使用asyncio.gather()等方式同时发起多个数据库查询,比如批量获取Post后,并行加载每个Post的标签并完成验证,而非逐个处理。

  • N+1查询问题未解决:同步和异步版本都存在严重的N+1查询:先查询所有Post(1次),再为每个Post查询标签(N次),额外还有每个Post的count查询(N次),总计1+2N次查询。异步仅将同步阻塞查询替换为异步非阻塞,但查询次数未减少,串行执行下总耗时与同步版本差异极小。应使用aprefetch_related(异步版预加载)替代循环查询,将查询次数降至1-2次,再对比性能才有意义。

  • 数据库驱动未适配异步:需确保使用真正支持异步的数据库驱动,比如PostgreSQL用asyncpg,MySQL用aiomysql。若仍使用同步驱动(如psycopg2),Django会在异步视图中通过线程池执行同步查询,异步的性能优势会被线程池开销抵消,甚至更慢。

  • 测试场景未覆盖高并发:异步的性能优势通常在高并发场景下才显著,单个请求的异步执行耗时与同步差异不大,甚至因异步调度开销略高。需用ab、wrk等工具模拟多并发请求,对比同步与异步视图的吞吐量(每秒处理请求数),而非单个请求耗时。

  • ASGI服务器配置不当:若使用WSGI服务器运行异步视图,Django会兼容处理但仍依赖线程池,无法发挥异步真正优势。需配置ASGI服务器(如Uvicorn、Daphne),确保异步代码直接运行在异步事件循环中。

  • IO等待占比不足:异步的优势在于减少IO等待时间,若业务逻辑中IO等待占比极低,异步调度、上下文切换的开销可能抵消甚至超过IO节省的时间。只有当单个请求包含大量IO操作(如多数据库查询、外部API调用)时,异步才能体现性能提升。


内容的提问来源于stack exchange,提问作者Salaah Amin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 13:52:46