1

注意:我对 django 和数据库都是新手,所以请原谅我的无知。

我正在尝试在 django 中实现一个论坛,并希望有粘性线程。我想这样做的天真方法是像这样定义 Thread 模型:

class Thread(models.Model):
    title = models.CharField(max_length=max_title_length)
    author = models.ForeignKey(Player, related_name="nonsticky_threads")
    post_date = models.DateField()
    parent = models.ForeignKey(Subsection, related_name="nonsticky_threads")
    closed = models.BooleanField()
    sticky = models.BooleanField()

然后要获得粘性线程,请执行以下操作:

sticky_threads = Thread.objects.all().filter(sticky=True)

问题在于,至少在理论上这具有 O(n) 复杂度,这听起来很糟糕。(因为粘性线程总是显示在第一页,所以这个查询会相当频繁地运行)但是,我不知道数据库/django 的聪明程度会如何影响最终的性能,或者它是否仍然会很糟糕。

我目前的替代方法是创建不同的 Thread 和 Sticky_Thread 类:

class Thread(models.Model):
    title = models.CharField(max_length=max_title_length)
    author = models.ForeignKey(Player, related_name="nonsticky_threads")
    post_date = models.DateField()
    parent = models.ForeignKey(Subsection, related_name="nonsticky_threads")
    closed = models.BooleanField()
class Sticky_Thread(models.Model):
    title = models.CharField(max_length=max_title_length)
    author = models.ForeignKey(Player, related_name="sticky_threads")
    post_date = models.DateField()
    parent = models.ForeignKey(Subsection, related_name="sticky_threads")
    closed = models.BooleanField()

无论如何,让我在 O(1) 时间内抓住粘性线程。我不喜欢这种方法的是,现在如果我只想获取玩家的所有线程,我必须实现一个特殊的线程属性,如下所示:

class Player(models.Model):
    [snip]

    @property
    def threads(self):
        return self.sticky_threads | self.nonsticky_threads

这种方法感觉很难看。

有没有明显最好的方法来实现这样的事情?我是否只需要计时,看看这种幼稚的方式是否可以接受?(我将其作为一个学习练习来实施,所以我并没有硬性限制,这让这个检查有点困难)(如果是这样,你会建议我怎么做?(像 timeit 这样的坏方法吗?)有更好的选择吗?

谢谢!

4

1 回答 1

3

您对这两个操作的复杂性的分析是遥不可及的。将过滤器操作分类为 O(n) 并将两个单独的类分类为 O(1) 根本不正确——我不知道你用什么来区分。数据库针对单个条件进行选择进行了高度优化:sticky列上的索引将使过滤查询几乎与从单独的表中查询所有内容完全相同。

第一种方法毫无疑问是正确的方法,只要您确保您的sticky列被索引。

于 2013-06-22T18:52:20.687 回答