SQL表中的键值对

时间:2018-12-02 15:45:26

标签: sql django django-models database-design

我正在构建Django应用,我想在主页上显示一些统计信息,例如交易总数,成功交易的百分比,每日活跃用户数等。

由于性能原因,我不想每次用户请求主页时都在视图中计算这些值。我想到了两种可能的解决方案。

(1)创建多个单记录表

为每个统计信息创建一个表,例如:

from django.db import models

class LastSuccessfulTransactionDate(models.Model):
    date = models.DateTimeField()

class TotalTransactionAmount(models.Model):
    total_amount = models.DecimalField(max_digits=8, decimal_places=2)

# ...

并确保每个表中仅存在一条记录。

(2)创建具有键值数据的表

class Statistics(models.Model):
    key = models.CharField(max_length=100)
    value = models.TextField()

并通过执行以下操作保存数据:

from datetime import datetime
from decimal import Decimal
import pickle

statistics = {
    'last_successful_transaction_date': datetime(2010, 2, 3),
    'total_transaction_amount': Decimal('1234.56'),
}
for k, v in statistics.items():
    try:
        s = Statistics.objects.get(key=k)
    except Statistics.DoesNotExist:
        s = Statistics(key=k)
    s.value = base64.b64encode(pickle.dumps(v, pickle.HIGHEST_PROTOCOL)).decode()
    s.save()

并通过以下方式检索:

for s in Statistics.objects.all():
    k = s.key
    v = pickle.loads(base64.b64decode(s.value.encode()))
    print(k, v)

在这两种情况下,数据都将不时地通过cron作业进行更新(它们不必非常精确)。

对我来说,解决方案(2)看起来更好,因为要显示主页,我只需要从Statistics表中获取数据,而不是从许多单记录表中获取数据。是否有针对此问题的建议解决方案?谢谢

1 个答案:

答案 0 :(得分:0)

如果使用的是property descriptor,则是更好的解决方案。您可以将键值对直接存储在JSONField中。尝试这样:

# model
class Statistics(models.Model):
    records = JSONField()

# usage
statistics = {
    'last_successful_transaction_date': datetime(2010, 2, 3),
    'total_transaction_amount': Decimal('1234.56'),
}

Statistics.objects.create(records=statistics)

Statistics.objects.filter(records__last_successful_transaction_date= datetime(2010, 2, 3))  # Running query

s = Statistics.objects.filter(records__last_successful_transaction_date= datetime(2010, 2, 3)).first()
new_statistics = {
    'last_successful_transaction_date': datetime(2012, 2, 3),
    'total_transaction_amount': Decimal('1234.50'),
}
records = s.records
records.update(new_statistics)
s.records = records
s.save()