以天为单位的日期时间差异的高性能计算

Posted

技术标签:

【中文标题】以天为单位的日期时间差异的高性能计算【英文标题】:Performant calculation of datetime diffs in days 【发布时间】:2018-04-02 12:27:42 【问题描述】:

我有一个 Django 模型,其中包含一条带有 date 的唯一记录。我目前正在将记录计入天数范围内,例如X 号码已经过了今天的日期,X 将在接下来的 10 天内发生,X 将在接下来的 30 天内发生。 下面的代码是我目前使用的代码,它从针对模型的 records.objects.all() 查询中提取所有值,然后循环遍历每个对象以计算日期时间增量并增加相关计数器。

for x in records:
    if x.date is None:
        missingValue += 1
    else:
        delta = x.date - date.today()
        if delta.days < 0:
            passed += 1
        if delta.days < 10:
            tenDays += 1
        if delta.days < 30:
            thirtyDays += 1

对于大约 50,000 条记录,这大约需要 5-6 秒,这比我希望的要长,我正在尝试减少此时间,因为记录数量可能会增加。 问题实际上是关于日期时间差异的性能计算和对结果天数进行分组,就好像有更好的方法通过 Django Query 或其他我找不到的方法,我愿意尝试它。

我已经探索过在原始 SQL 中使用 DateAdd,但它似乎需要我为每个日期范围查询数据库,并且仍然会导致我需要遍历结果。

【问题讨论】:

请准备rextester.com 演示与示例数据和所需的输出。我确信在纯 SQL 中我们可以得到低于 1 秒的时间。 rextester.com/AWPX46055 - 认为我做对了。期望的输出只是上述组返回的数字,在十天内,在三十天内通过。我还看到未来需要超过 30 天的任何东西。内日期是累积的。 感谢样本数据 【参考方案1】:

使用 SQL 窗口化COUNT:

WITH cte AS (
     SELECT *,CASE WHEN DATEDIFF(DAY,GETDATE(),targetdate) <=0  THEN 0
                   WHEN DATEDIFF(DAY,GETDATE(),targetdate) <=10 THEN 10
                   WHEN DATEDIFF(DAY,GETDATE(),targetdate) <=30 THEN 30
                   ELSE 31 END AS grp
     FROM [record]   
     --WHERE targetdate > GETDATE() - 60  -- last 60 days
)
SELECT DISTINCT grp, COUNT(*) OVER(ORDER BY grp) AS running_count
FROM cte;

Rextester Demo

【讨论】:

非常感谢,现在响应时间不到秒【参考方案2】:

在优化性能之前,我会考虑批量执行。您最小的变化窗口似乎是 1 天。因此,通过过滤记录模型中的“更新”字段,您可以每小时(每个 cron)调用一次:

from datetime import datetime, timedelta
records.objects.filter(updated__lt = datetime.now()-timedelta(days=1))[:2083]

然后做你的操作。 请注意,您可以限制检索到的记录数。因此,每小时您将处理 2083 条(或 5000 条)记录来划分一天中的任务。这个数字可以根据数据库中的记录数进行缩放(例如 50000/24 = 2083)

此外,您的迁移可能希望反映您希望将其设置在过去,以便在开始时处理每条实时记录。

【讨论】:

你说得对,最小的窗口是 1 天。目前,我正在获取结果并将其直接呈现给用户(问题的一部分)。使用这种方法,我想我可以缓存结果并在每次用户查看数字时调用它,而不是即时计算它们 是的,这里的重点是,无论您发现自己在哪里写Model.objects.all(),都应该考虑过滤,以减轻数据库的压力。如果你能找到其他过滤方式,那就太好了。例如。当用户执行操作时,更新与该用户关联的所有记录。每小时批处理是详尽的解决方案,可避免忘记记录。

以上是关于以天为单位的日期时间差异的高性能计算的主要内容,如果未能解决你的问题,请参考以下文章

如何以天为单位注释日期时间的差异

Android/Java - 以天为单位的日期差异

Pandas Timedelta 以天为单位

计算 Hive 数组中连续日期之间的差异

使用数据帧中的某些参数计算日期之间的差异

两个日期之间的天数差异[重复]