比较两个字段的django查询速度越来越慢

时间:2014-08-02 05:49:20

标签: python django orm

我的设置类似于以下内容:

class TimeFrame(models.Model):
    """A range of dates and times.  On each date in the given range,
        associated objects are available only within the provided time
        range.
    """
    class Meta:
        index_together=(('time_from','time_until'),)

    date_from = models.DateField(db_index=True)
    date_until = models.DateField(db_index=True)
    time_from = models.TimeField(db_index=True)
    time_until = models.TimeField(db_index=True)

    scheduled_model = models.ForeignKey(ScheduledModel)

time_until可能会小于time_from,这会使情况严重复杂化。例如,某些东西可能在晚上9点到凌晨2点之间提供。我已经编写了一个过滤器来查找可用的TimeFrame,如下所示:

open_time_frame_filter = (
    Q(
        # Cases like 9pm-2am.
        Q(time_from__gt=F('time_until')),
        Q(
            # Past 9pm.
            time_from__lte=time,
            date_from__lte=date,
            date_until__gte=date
        ) | Q(
            # Before 2am.
            time_until__gte=time,
            date_from__lte=date - datetime.timedelta(days=1),
            date_until__gte=date - datetime.timedelta(days=1)
        )
    ) | Q(
        # Normal cases.
        Q(time_from__lte=F('time_until')),
        Q(time_from__lte=time),
        Q(time_until__gte=time),
        Q(date_from__lte=date),
        Q(date_until__gte=date)
    )
)
可以预见,

timedate是时间和日期。不幸的是,这里的某些东西是非常低效的,并且最终效率低于仅仅检索适合并在python中迭代它们的所有TimeFrame。在使用古老的跟踪方法(评论出来)来发现根本原因之后,它似乎是F个对象的行,其中一个字段与另一个字段进行比较,这会减慢查询速度。我需要能够在这里使用过滤器以获得灵活性,但是由于当前的低效率,它太慢了。为了与项目的其余部分保持一致,我希望远离原始SQL。但是,我不确定从哪里开始解决这类问题。

修改

TimeFrame个对象在时间范围内通过外键绑定到一个单独的对象(多对一)。然后更精确地描述过滤器:

class ScheduledModel(models.Model):
    """A model with an associated schedule (described by several time
        frames).
    """

    @property
    def is_open(self):
        """Is the model currently open?"""
        time = datetime.now().time()
        date = datetime.now().date()
        return TimeFrame.objects.filter(
            Q(scheduled_model_id=self.id),
            open_time_frame_filter # As defined above.
        ).exists()

在手动python版本中,首先通过id检索时间帧的查询集,然后迭代以确定是否有任何打开。原则上,这个查询应该做同样的事情,并且会更快,因为time_from,time_until,date_from和date_until被索引,time_from和time_until被索引在一起。每个预定模型只有大约十个时间帧,但总共有数十万个时间帧。

编辑2

我已经纠正了原始模型,以明确已经尝试过的内容。

0 个答案:

没有答案