【问题标题】:Can I batch incrementing values in order to reduce database writes?我可以批量递增值以减少数据库写入吗?
【发布时间】:2015-06-26 14:57:41
【问题描述】:

我的网络应用在 Heroku 上使用 Django。

该应用有两个组件:横幅服务 API 和报告 API。

应用提供的横幅包含对应用报告 API 的 ajax 调用。每次展示都会进行一次此调用。这样做的目的是记录每个横幅每天获得的展示次数。

报告 API 节略来源:

def report_v1(request):
    '''
    /report/v1/?cid=

    - cid= the ID of the banner
    '''

    creative = get_creative(creative_id = request.GET.get('cid'))
    if not creative:
        return HttpResponseNotFound("404 creative with that ID not found")

    day = timezone.now()

    fact, created = CreativeFact.objects.get_or_create(
        day = day,
        app = app,
        creative = creative,
        defaults = {
                'impression_count': 0,
            }
        )

    fact.impression_count += 1

    response = HttpResponse("200 OK")
    response["Access-Control-Allow-Origin"] = "*"

    return response

我的问题:有什么方法可以避免每次展示都写入数据库?我目前正在以这种方式跟踪数十万次展示,并且预计很快就会跟踪数百万次,我认为这种方式效率低下。

【问题讨论】:

  • 我不太了解 Django,但在大多数平台上,我建议您将类似 CSV 的数据写入临时文件。然后定期用一个空的临时文件和COPY ... FROM stdin 将旧临时文件旋转到数据库中以加载其内容,可能加载到一个临时表中,然后加入以更新/插入真正的目标表。由于您使用的是“get_or_create”,我猜您想加载到临时文件中,然后进行批量更新;见stackoverflow.com/q/17267417/398670

标签: python django postgresql heroku


【解决方案1】:

您可以缓存计数,然后以 100 或任何最佳值的增量将它们写入模型:

report_v1 顶部:

if getattr(report_v1, 'cache', None) is None:
    report_v1.cache = {}

然后,在您验证 cid 有效之后(在带有 404 响应的行之后):

if cid in report_v1.cache:
    report_v1.cache[cid] += 1
else:
    report_v1.cache[cid] = 1

然后,您希望仅在特定时间间隔增加模型上的值:

if not report_v1.cache[cid] % 100:
    #increment impression_count 
    #wipe cache

这种方法的缺点是缓存在内存中,所以如果应用崩溃,它就会丢失。

【讨论】:

  • 这似乎很有帮助,谢谢!您能否指出缓存属性的文档方向? (我以前从未实现过缓存。)
  • 它只是一个通用属性,而“缓存”只是一个任意名称,因此没有具体的文档。不过要意识到的重要一点是cache 是函数的一个属性——它不是一个局部变量。
猜你喜欢
  • 2012-11-19
  • 2022-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-05
  • 1970-01-01
  • 2016-12-10
  • 1970-01-01
相关资源
最近更新 更多