【问题标题】:Efficient database design for billing用于计费的高效数据库设计
【发布时间】:2015-11-03 06:52:05
【问题描述】:

我有一个简单的需求,但没有什么设计经验。

每个客户请求旋转照片将花费 1 美分。我需要在表中添加每个请求以用于历史记录:

CREATE TABLE Rotate_Photo
(
license VARCHAR(35),
reqtype INT NOT NULL, --each will cost 1 cent
updated TIMESTAMP,
FOREIGN KEY (license) 
        REFERENCES customer(license)
        ON DELETE CASCADE
        ON UPDATE CASCADE
)ENGINE=InnoDB;

现在另一个 Payments 表将保存每个客户的信用余额。

CREATE TABLE Payments (
license VARCHAR(35),
Amount FLOAT(5,0) NOT NULL,
receive_date DATE NOT NULL,
updated TIMESTAMP,
FOREIGN KEY (license) 
        REFERENCES customer(license)
        ON DELETE CASCADE
        ON UPDATE CASCADE
) ENGINE=InnoDB;

我如何知道客户何时失去平衡?鉴于服务器每秒会收到很多请求。

如果有请求,我可以汇总 Rotate_Photo 中的所有记录,以了解已收到多少请求并减去客户信用。但是会不会很低效?

有什么更好的方法?

【问题讨论】:

  • 您是否测量过对记录进行计数/求和所需的时间?

标签: mysql database-design


【解决方案1】:

选项 1

如你所说

付款表将保留贷方余额

因此,当一个请求来的时候,你需要查询客户端的余额,检查是否为正数。

SELECT Amount from Payments where license = :Rotate_Photo.licence;

您可以使用 count() 函数以有效的方式从 Rotate_Photo 获取记录数。

SELECT count(*) AS rotation_count from Payments where license = :Rotate_Photo.licence;

选项 2

一个更有效的设计可能是保持与许可证记录的平衡。

然后你会有一张许可证表:

CREATE TABLE Payments (
license VARCHAR(35),
Amount FLOAT(5,0) NOT NULL,  -- current balance
purchased_amount FLOAT(5,0),  -- amount purchased so far
receive_date DATE NOT NULL,
updated TIMESTAMP,
FOREIGN KEY (license) 
        REFERENCES customer(license)
        ON DELETE CASCADE
        ON UPDATE CASCADE
) ENGINE=InnoDB;

显然,每次购买时,您都必须管理 amount 和 purchase_amount 字段(减少 amount 并增加 purchase_amount)。

这种方法的缺点是您无法获取特定时间段(例如一个月)的统计信息,但您可以获得帐户的快照。

优点是您需要一次读取和更新来管理金额。

【讨论】:

  • 但是花了多少钱将来自 Rotate_Photo 表,该表将是 0.1* 的记录总数。
  • 哦是的 .. 但它够快吗?这个查询每秒运行几次?
  • 通常,如果您在过滤器字段上添加索引并优化表,count(*) 将足够快。但是,如果您每秒运行几次(这在您的问题中没有明确说明,所以也许添加这个重要的事实)创建另一个表来存储计数可能是有意义的。您可能还需要考虑将表引擎更改为 MyISAM。参考:stackoverflow.com/questions/1332624/…
【解决方案2】:

“更好”是主观的——但我强烈建议首先构建一个规范化的解决方案(这意味着动态计算余额),并且只有在遇到无法通过更好的查询解决的性能问题时才去规范化,归档策略,或更大的硬件。

在现代系统上,这可能意味着数千万或数亿条记录。

如果您真的对此感到担忧,请构建一个测试工具,其记录数量是您期望在生产中拥有的记录数量的两倍,并查看您的应用程序的执行情况。

您担心的性能问题有多种解决方案。

最常见的是“非规范化” - 每次用户付款或使用服务时,您都会更新他们个人资料上的“currentBalance”字段。您可以在应用程序逻辑中或使用数据库触发器来执行此操作。应用逻辑意味着每一段处理金钱的代码都需要正确处理;只有一个错误可能意味着您正在放弃免费的图像旋转。数据库触发器难以测试、难以维护,并且会产生自身的性能问题。

【讨论】:

  • 您说“即时计算余额”,但我不应该每月运行一次程序来验证即时计算是否正确。就像生成最终报表之前的电话账单或信用卡使用量一样。
猜你喜欢
  • 2016-12-04
  • 1970-01-01
  • 2011-06-10
  • 1970-01-01
  • 1970-01-01
  • 2018-10-02
  • 2012-02-12
  • 2016-01-24
  • 1970-01-01
相关资源
最近更新 更多