【问题标题】:Key-value pairs in SQL tableSQL表中的键值对
【发布时间】:2019-05-04 01:04:08
【问题描述】:

我正在构建一个 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 表中获取数据,而不是从多个单记录表中获取数据。这个问题有什么推荐的解决方案吗?谢谢

【问题讨论】:

    标签: sql django django-models database-design


    【解决方案1】:

    如果您使用 Postgresql,还有更好的解决方案,即JSONField。您可以直接将键值对存储在 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()
    

    【讨论】:

    • 嗯,这取决于你想如何使用它。我建议为每个统计数据创建新条目。但是,如果您想将所有内容保留在同一数据库行中,请查看我的更新答案
    • @b1000 太棒了:)。考虑accepting this as an answer如果它对你有帮助:)
    • 这看起来不错,比腌制和编码/解码更容易,谢谢。
    猜你喜欢
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多