0%

Django Admin 慢查询优化

项目是 Django Admin 的简单的后台,有一个表大概有160万左右的数据,打开一次需要将近20s,借助django-debug-toolbar 进行优化一下。

背景

Django Admin 构建的后台,使用Simpleui优化显示效果,
数据量160万左右,Admin 结构如下:
admin-model-1

定位

  • 安装 django-debug-toolbar

  • 看到加载了17s,通过Chrome Deubug 没发现网页资源 有明显问题,那就从这109个SQL查询入手
    admin-debug-2

  • 展开第一个慢SQL,发现有两次count,count需要走全表扫描,数据多时影响查询性能。
    admin-debug-3
    通过查阅文档发现一次是受show_full_result_count参数控制(控制是否应在过滤的管理页面(例如)上显示对象的全部数量。如果此选项设置为, 则显示类似的文本。99 results (103 total)False99 results (Show all) )可以在 Admin Class 里关掉。

1
show_full_result_count = False
  • 少了一个count,速度没啥提升。继续看下面的SQL:
    admin-debug-4
    存在好多 DISTINCT 查询,还是会走全表扫描影响性能,StackoverFlow上说是list_filter(#过滤框导致的默认从表中取出该字段的所有字段,以支持过滤补全。可以通过自定义Filter来控制行为),这里选择使用search_fields代替list_filter。

  • 现在这个sql 已经从5s多变成了2s多:
    admin-debug-5
    发现有很多类似的小查询,虽然每条查询不慢,但是架不住多,StackoverFlow说是因为表上有外键,每条记录都会单独查询外键表,可以通过联合查询来避免。 admin.ModelAdmin支持通过list_select_related参数(转化为数据库层面的left join 以提高查询速度)

1
list_select_related = ["webhook", "processing_method"]
  • 现在 只剩下4个sql 查询了,整个页面用时1.6s,sql用时500ms:
    admin-debug-6
  • Django Admin 默认每页展示100条记录,设成20条,又快了一点。
1
list_per_page = 20

扩展

  • 对于大量数据的count,也是可以权衡准确性来优化速度的,详情可以参考HylaruCoder大佬的
    MG的编程物语 通过返回假数据,设置缓存,利用DB特性返回大概值等方式。

参考

欢迎关注我的其它发布渠道