如何记录对Django model字段的访问情况以清理冗余模型字段
方案1:重写模型的
__getattr__方法实现字段访问统计 这是最轻量的无依赖方案,适合临时统计场景:
- 首先给你的模型增加访问统计逻辑,示例代码如下:
from django.db import models class Person(models.Model): # 你的原有字段,比如 person_id = models.IntegerField(primary_key=True) name = models.CharField(max_length=100) age = models.IntegerField() # ... 其余100+字段 # 新增统计逻辑 _accessed_fields = set() def __getattr__(self, name): # 仅统计模型存在的业务字段,忽略私有属性、方法 if name in [f.name for f in self._meta.fields] and not name.startswith('_'): self._accessed_fields.add(name) return super().__getattr__(name) @classmethod def clear_accessed_stats(cls): cls._accessed_fields = set() @classmethod def get_accessed_fields(cls): return list(cls._accessed_fields)
- 使用流程:
- 统计前先调用
Person.clear_accessed_stats()清空历史统计数据 - 正常执行业务代码,包括你示例的
Person.objects.get(person_id=123)以及后续对实例的字段读取操作 - 统计周期结束后调用
Person.get_accessed_fields()即可拿到所有被访问过的字段列表
- 统计前先调用
注意:该方案统计的是模型实例层面的字段读取操作,如果代码中用到了
values()/values_list()这类直接返回字典/元组、不生成模型实例的ORM方法,不会被统计到,需要配合方案2覆盖这类场景。
方案2:通过Django数据库查询日志统计查询加载的字段
如果你需要统计ORM查询本身请求的字段(比如默认get方法会查询所有字段,加了only()/defer()则会查询指定字段),可以开启查询日志实现:
- 临时在settings.py中添加配置开启查询日志:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': False, }, }, }
- 执行ORM查询后,日志会输出完整的SQL语句,直接查看SQL的
SELECT后的字段列表,就能明确本次查询请求了哪些字段。
后续优化建议
- 对比统计到的被访问字段和模型全字段列表,长时间未被访问的字段可以先做软删除(标记为废弃,观察1-2个版本无报错后再正式删除)
- 对于仅需要访问少量字段的高频查询,可加上
only()指定需要的字段,减少数据库IO和内存占用,比如仅需要姓名时用Person.objects.only('name').get(person_id=123)
内容的提问来源于stack exchange,提问作者gitnewb
相关产品推荐
相关产品推荐

