0

我有创建(或接收)交易的用户。我拥有的交易层次结构是一个多表继承,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's wonderful IneritanceManager,效果很好。除了当我在传输子模型的接收者 FK 字段上包含过滤时,数据库查询增加了一个数量级。

如上所示,我在 Transactionuser列和 Transferrecipient列上放置了索引。但在我看来,如果可能的话,我可能需要一个关于 Transaction 子类型的索引。我试图通过在 Transactiontype字段上放置索引并将其包含在查询中来实现此效果,如下所示,但这似乎没有效果。此外,我使用.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?我错过了什么吗?我在做傻事吗?或者有没有办法可以进一步优化?

4

0 回答 0