向数据库模型添加额外字段以加速数据库查询是一种好习惯吗?

时间:2016-05-24 12:06:55

标签: django database database-design django-models django-views

我有两个数据库模型的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的外键。在这种情况下,根本不会有任何复杂的数据库请求。

现在我有几个问题:

  • 向模型添加冗余字段是一个好习惯吗?

  • 是否可以编写迁移规则以将此冗余字段填充到所有当前设备?

  • 最重要的是,加快计算的其他选择是什么?

1 个答案:

答案 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_atsave()值的最新条目。

然后执行循环并从列表中获取值,而不是在每次迭代时调用数据库。

但是,像您建议的那样,对数据库进行非规范化也是一个好主意。使用"冗余字段" 可以绝对是好习惯。您可以在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

此外,您还可以将设备DeviceTestdevtests = 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; }; 列表。