bigywater.tech
Django · 33

values()、values_list() 与对象查询性能

只要几个值的时候,什么时候该用 values() / values_list()?省多少?这篇用 5 万行数据量出耗时和峰值内存,并说明 values 系列失去了什么。

134 → 18 ms
5 万行:完整模型对象 → values_list(flat=True) 的耗时
42 → 5.1 MiB
同样两种取法的峰值内存(tracemalloc)
only() 还是对象
only("a") 构造的仍是模型实例,耗时与全字段接近

耗时与内存

实测 · 本机执行输出
对象:Row.objects.all()                                    134.1 ms   峰值内存    42.3 MiB   类型 Row
对象:only('a')                                            122.8 ms   峰值内存    24.9 MiB   类型 Row
values('a', 'b')  → dict                                 28.6 ms   峰值内存    16.6 MiB   类型 dict
values_list('a', 'b')  → tuple                           23.9 ms   峰值内存     7.8 MiB   类型 tuple
values_list('a', flat=True)  → int                       17.6 ms   峰值内存     5.1 MiB   类型 int
values_list(全部列)  → tuple                                40.7 ms   峰值内存    24.3 MiB   类型 tuple
values()(全部列) → dict                                     52.0 ms   峰值内存    33.1 MiB   类型 dict

耗时每种取 3 次中最快的一次(不带 tracemalloc);内存是另开一次用 tracemalloc 量的峰值。(我第一次把两者混在一起量,tracemalloc 把耗时放大了近 7 倍,后来拆开了。)

每种写法的类型

实测 · 本机执行输出
对象     : Row  每个对象带 __dict__ 与 _state: ['_state', 'a', 'b', 'c', 'd', 'id'] …
values   : {'a': 0, 'b': 'bee-0'}
values_list: (0, 'bee-0')
flat     : 0
named    : Row(a=0, b='bee-0')
实测 · 本机执行输出
对象能用模型上的属性(如 __str__ 等),values() 只有列:
  values 的 key: ['id', 'a', 'b', 'c', 'd']

取舍:需要模型上的方法 / 属性 / 信号 / 关系访问就用对象;只要数据(导出、聚合前的中间值、大批量处理)用 values / values_list;只想省一列大字段,only / defer(第 29 篇)。

分步演示:对象与值

values 与对象
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。SQLite,50000 行,c 列 40 字符、d 列 200 字节
    • 没有验证:PostgreSQL / MySQL 上网络传输带来的差别、iterator() 与 chunk_size 对内存的影响(第 102 篇)、CPython 版本差异、values() 对带 from_db_value 的自定义字段的转换(第 38 篇)
    京ICP备2026067502号-1京公网安备11010502063487号