我有两个数据库模型的Django项目:Device和DeviceTest。
系统中的每个设备都应该经历从制造到销售的一些测试阶段。因此,许多DeviceTest对象通过外键关系连接到Device对象:
GridView
在我的项目中有2种页面:
1)包含单个设备的所有测试的页面
2)包含所有设备及其最新状态和操作的页面
现在我正在尝试优化2)页面。要获取最新的测试数据,我使用以下代码:
class Device(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=255)
class DeviceTest(models.Model):
device = models.ForeignKey(Device)
created_at = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=255)
tester = models.CharField(max_length=255)
action = models.CharField(max_length=255)
目前在我的数据库中~600个设备和~4000个测试。这是页面加载的主要瓶颈。
加快此计算的方法有哪些?
我想出了为Device model添加额外字段的想法:它的最后一个DeviceTest的外键。在这种情况下,根本不会有任何复杂的数据库请求。
现在我有几个问题:
向模型添加冗余字段是一个好习惯吗?
是否可以编写迁移规则以将此冗余字段填充到所有当前设备?
最重要的是,加快计算的其他选择是什么?
答案 0 :(得分:1)
id_list = [dev.id for dev in device_list]
devtests = DeviceTest.objects.filter(
device_id__in=id_list).order_by('-created_at').distinct('device')
在一次数据库调用中,这应该只在devtests
中为每个device_id
提供create_at
个save()
值的最新条目。
然后执行循环并从列表中获取值,而不是在每次迭代时调用数据库。
但是,像您建议的那样,对数据库进行非规范化也是一个好主意。使用"冗余字段" 可以绝对是好习惯。您可以在post_save()
方法中自动执行非规范化,也可以通过侦听相关模型中的.distinct('device')
信号来自动化。
修改强>
首先进行更正:应为id
(非created_at)
列表解析,仅从device_list中获取Device.objects.filter(...).values_list('id', flat=True)
值。相当于id_list = [dev.id for dev in device_list]
id
使用DeviceTest
的列表,我们会获取所有相关的devtests = DeviceTest.objects.filter(device_id__in=id_list)
个对象
created_at
并按-created_at
排序,但最新的Device
。这也意味着,对于每个DeviceTest
,最新的相关.order_by('-created_at')
将是第一个。
device
最后,对于每个.distinct('device')
,我们只选择我们找到的第一个相关值(这将是最新的,因为我们按这种方式对值进行排序)。
id
此外,您还可以将设备DeviceTest
和devtests = DeviceTest.objects.filter(device_in=Device.objects.filter(...))
查找
JOIN
然后Django会为它创建SQL以在数据库中执行id
,因此您不需要在Python中加载和循环class Vertex
{
public:
Vertex( float x = 0,
float y = 0,
float z = 0)
: x(x), y(y), z(z) {}
float x, y, z;
};
列表。