我有一个用户执行操作并接收积分的应用程序。在应用程序中执行算法并使用结果值更新点数据库字段或让数据库进行数学计算会更好吗?
假设0分的用户将额外收到2个:
//app does the math (0+2) and issues this statement
update users set points = 2 where id = 1
VS
//app only knows to update by 2, db does the math
update users set points = points+2 where id = 1
SQL性能方面有什么不同吗?就应用程序设计而言,一种方法比其他方法更好,这种逻辑应该存在,等等?
编辑:此编辑可能来得太晚,无法提供更好的服务,但我只想回复一些反馈并做出澄清。虽然我对任何db性能差异感到好奇,但这不是关注。我担心的是这种逻辑最好的存在,以及为什么一个人应该优先于另一个以及在哪些情况下。
一方面,我的几乎所有逻辑都存在于应用程序中,因此在那里进行数学运算是一致的like Hank's answer。但另一方面,有一些潜在的延迟/线程问题可能表明逻辑应该由数据库执行,由Blixt和Andrew提出。
答案 0 :(得分:5)
这两项行动有所不同。第一个说:
用户应该有两点;不多也不少。
第二个说:
除了他/她已经拥有的东西之外,用户还应该得到两分。
我不会将这种数据逻辑放在业务逻辑层中。业务逻辑应该是“用户获得两点”,它应该告诉数据库。不应该自己动手并说“数据库告诉我用户有两点,所以现在他们有四个!”如果业务层和数据库之间存在延迟,或者在多个线程中同时进行很多更新,则这很危险。
我意识到我实际上没有在明文中提出我更喜欢的选择:
在业务逻辑中确定用户应获得多少积分。然后发出一个语句,告诉数据库按这些点增加用户的分数。通过这样做,您使数据库负责保持数据的一致性,这是一项应该只属于数据库的任务。我的意思是他们做的,对吧?
UPDATE users SET points = points + ? WHERE user_id = ?;
您的业务逻辑层只会填空。
如果你正在做一个庞大的项目,你甚至可以考虑将它放在一个存储过程中,因为你将来可能会更改数据结构(例如将点分解到另一个表或其他表): / p>
userChangePoints ?, ?
答案 1 :(得分:4)
虽然在某种意义上它可以被视为过早优化,但对于多线程/用户环境而言,两者之间的差异非常关键,因为直接读取然后设置值允许两个事务干扰并导致其中一个他们可能会迷路。
使用points = points + 2发送积分更新至少隔离两个语句,但如果同时由不同用户提交两次,则会得到4的结果。
同样可能不适合情况/应用,但我认为您的选择应考虑您需要的隔离/保护。
这对应用程序是特定的,用户可以登录两次等,但两者之间的差异原则仍然存在。
答案 2 :(得分:3)
我认为这是“过早优化”或过度优化的情况。
答案是:没关系。做任何使您的应用程序更简单,清晰和可维护的东西。
ADDED:关于性能,除非您对表中的所有数据运行此更新,否则我认为您没有发现任何差异。但是如果你必须知道,我相信第二个选项将需要更多的机智,因为你首先需要读取值,然后根据它计算然后再写回来。因此,您可以使用第一个选项进行一次读取操作。
答案 3 :(得分:1)
将其添加到执行其余业务逻辑的任何位置。如果您的应用程序允许数据库处理所有业务逻辑,请在SQL中进行数学运算。如果您的业务逻辑位于应用程序层中,请将数学放在那里并发出简单的UPDATE
。
答案 4 :(得分:0)
我会说和镇上的新人一样,不要担心太多。
我会写出有意义且更容易阅读的内容(所以第一个),然后分析两种方式,然后根据需要进行更改。