基础模型的继承模型上的FK关联的查询优化

时间:2020-03-13 07:04:06

标签: django django-models orm multi-table-inheritance

我有创建(或接收)交易的用户。我拥有的事务层次结构是多表继承,以Transaction为基础模型,其中包含所有事务类型(例如,用户(FK),金额等)之间的公共字段。我有几种事务类型,它们进行了扩展具有特定类型数据的Transaction模型。

为了这个示例,可以在下面找到说明我的问题的简化结构。

from model_utils.managers import InheritanceManager

class User(models.Model):
    pass

class Transaction(models.Model):
    DEPOSIT = 'deposit'
    WITHDRAWAL = 'withdrawal'
    TRANSFER = 'transfer'

    TYPES = (
        (DEPOSIT, DEPOSIT),
        (WITHDRAWAL, WITHDRAWAL),
        (TRANSFER, TRANSFER),
    )

    type = models.CharField(max_length=24, choices=TYPES)
    user = models.ForeignKey(User)
    amount = models.PositiveIntegerField()

    objects = InheritanceManager()

    class Meta:
        indexes = [
            models.Index(fields=['user']),
            models.Index(fields=['type'])
        ]

class Withdrawal(Transaction):
    TYPE = Transaction.WITHDRAWAL
    bank_account = models.ForeignKey(BankAccount)

class Deposit(Transaction):
    TYPE = Transaction.DEPOSIT
    card = models.ForeignKey(Card)

class Transfer(Transaction):
    TYPE = Transaction.Transfer
    recipient = models.ForeignKey(User)

    class Meta:
        indexes = [
            models.Index(fields=['recipient'])
        ]

然后,我在继承的模型的.save()方法中设置每个事务的类型。一切都很好。

当我想获取用户的交易时出现问题。具体来说,我需要子模型实例(存款,转移和提款),而不是基本模型实例(交易)。我还要求用户创建自己的交易以及已收到的转账。对于前者,我使用django-model-utils出色的IneritanceManager,效果很好。除了在转移子模型的收件人FK字段上包括过滤功能之外,数据库查询会增加一个数量级。

如上所述,我已将索引放在“事务user”列和“转移recipient”列上。但是在我看来,如果可能的话,我可能需要的是Transaction子类型的索引。我试图通过在Transaction type字段上放置一个索引并将其包括在查询中来实现这种效果,如下所示,但这似乎没有效果。此外,我将.select_related()用于用户对象,因为在序列化中是必需的。

查询的结构如下:

from django.db.models import Q

    queryset = Transaction.objects.select_related(
         'user',
         'transfer__recipient'
    ).select_subclasses().filter(
         Q(user=request.user) |
         Q(type=Transaction.TRANSFER, transfer__recipient=request.user)
    ).order_by('-id')

所以我的问题是,当在查询中包含Transfer.recipient时,为什么数据库查询会有一个数量级的差异?我错过了什么吗?我在做傻事吗?还是有办法进一步优化?

0 个答案:

没有答案
相关问题