哪个更具扩展性?ORM的distinct()还是Python的set()?

6

祝您新年快乐!

我有一个模型,它将保存数十万条记录。该模型如下所示:

class Transaction(models.Model):
    user = models.ForeignKey(User)
    client = models.ForeignKey(Client)
    amount = models.FloatField()

我想知道某个用户正在处理哪些客户端。为了获取唯一的客户端ID,我可以仅使用Django ORM:

Transaction.objects.filter(user=the_user).distinct('client_id').values_list('client_id', flat=True)

或者执行以下操作:
set(Transaction.objects.filter(user=the_user).values_list('client_id', flat=True))

两种方法都会产生相同的结果。但是在大量记录的情况下,哪一种方法更快?我知道distinct在数据库中是一个相对较慢的操作,但它与Python的set()相比如何呢?

最后,如果涉及到数据库,我的选择是MySql和PostgreSql用于生产环境。这两种方法在这种特定操作中是否有任何区别?


3
希望您在存储货币金额时不要使用浮点数。 - icktoofay
好的,假设我将使用Decimal,这只是一个快速的例子! :) - ppetrid
我希望.distinct依赖于RDBMS的实现,这可能比Python的set更快地实现唯一性。一个更好的问题是:“我使用timeit测量了时间,并得到了以下结果:blah、bleh、blih。为什么在我看到bluh和bloh时,blah比bleh更快?”作为一个模板示例。 - mmgp
我有点不安,你认为在数据库上使用DISTINCT比在Python上慢。这是一个普遍的观点吗?人们有什么理由支持这个观点吗? - David Aldridge
1
我并不相信任何事情,实际上我并不知道,这也是我首先提出问题的原因!我读到distinct是一个相对较慢的操作,我想让人们启发我,我不明白这会打扰到任何人。 - ppetrid
1个回答

10

我通常使用ORM函数,它更易读并在数据库层面运行,因此实际上是你的RDBMS计算不同值,并且你可以在一个步骤中得到结果。

您可以使用Python set来完成相同的操作,但需要首先将所有数据集带入,然后应用set()。因此,您需要执行两个步骤才能完成相同的操作。

在第一种情况下(ORM),您只有I/O开销,在第二种情况下,您有I/O开销+函数调用,因此我会选择ORM的distinct。


4
在第二种情况下,更重要的是你需要将(可能显著地)更多的数据从数据库传输到Python中,这会增加I/O开销。当然,好处是数据库可以减轻一些工作量,但希望数据库的“distinct”功能像Python的“set”一样有效或更有效。 - user395760
有趣的见解,内存折衷是一个重要因素,因为RDBMS无论如何都会加载所有记录。我会选择DISTINCT,并在有时间时进行适当的基准测试。谢谢大家! - ppetrid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接