the*_*dow 10 mysql normalization
我的问题是关于非规范化.在数据库中,何时应将派生数据存储在自己的列中,而不是每次需要时都计算它?
例如,假设您有用户为他们的问题获得Upvotes.您在其个人资料中显示用户的声誉.当用户被投票时,您应该增加他们的声誉,还是应该在检索他们的个人资料时计算它:
SELECT User.id, COUNT(*) AS reputation FROM User
LEFT JOIN Question
ON Question.User_id = User.id
LEFT JOIN Upvote
ON Upvote.Question_id = Question.id
GROUP BY User.id
Run Code Online (Sandbox Code Playgroud)
在使用自己的列以增量方式跟踪它之前,查询获得用户声誉的处理器密集程度如何?
继续我们的例子,假设一个Upvote的权重取决于投射它的用户有多少Upvotes(而不是多少声誉).检索其声誉的查询突然爆炸:
SELECT
User.id AS User_id,
SUM(UpvoteWeight.weight) AS reputation
FROM User
LEFT JOIN Question
ON User.id = Question.User_id
LEFT JOIN (
SELECT
Upvote.Question_id,
COUNT(Upvote2.id)+1 AS weight
FROM Upvote
LEFT JOIN User
ON Upvote.User_id = User.id
LEFT JOIN Question
ON User.id = Question.User_id
LEFT JOIN Upvote AS Upvote2
ON
Question.id = Upvote2.Question_id
AND Upvote2.date < Upvote.date
GROUP BY Upvote.id
) AS UpvoteWeight ON Question.id = UpvoteWeight.Question_id
GROUP BY User.id
Run Code Online (Sandbox Code Playgroud)
这与增量解决方案的难度远远不成比例.归一化何时值得,以及归一化的好处何时会失去非规范化的好处(在这种情况下是查询难度和/或性能)?
在拥有自己的列来逐步跟踪该用户名声之前,查询必须获得多大的处理器强度才能获得用户的声誉?
这里确实有两个问题,其中一个是幌子:(1)这种变化会提高性能吗?(2)性能改进是否值得努力?
至于性能是否提高,这基本上是标准的利弊分析。
标准化的好处基本上有两方面:
简化数据完整性
重新计算没有问题(例如,如果基础数据发生更改,则需要重新计算派生的列)。
如果您使用可靠实现的解决方案(例如,触发器,仅用于存储过程的数据更改和已撤销的直接表更改权限等)来覆盖数据完整性,那么这将成为计算验证源是否成本的直接方法。数据更改保证了每次都要重新计算派生数据与重新计算派生数据。(注意:另一种保持数据完整性的方法是强制按计划重新计算派生数据,在这种情况下,数据可能会在一定的时间容忍范围内不准确。StackExchange会采用此方法及其一些数字。)
在典型情况下(很多数据检索,而对基础数据的更改少得多),数学显然会偏向于将非标准化的派生数据保留在表中。
在一些罕见的情况下,基础数据经常发生变化,而派生数据却没有那么频繁地检索,这样做可能是有害的。
现在,我们提出了一个更重要的问题:性能改进是否值得付出努力?
请注意,与所有优化一样,最大的问题是“优化是否完全值得?”,因此有两个主要注意事项:
测量确切的性能差异并进行概要分析。
系统全局中特定优化的上下文。
例如,如果查询性能的差异(通常必须首先测量优化时的差异)在缓存的派生数据和计算得出的数据之间为2%,则实现信誉缓存列所带来的额外系统复杂性可能首先不值得。但是,只要有微不足道的改善,关怀与不关怀的门槛取决于应用程序的整体情况。如果您可以在其他地方采取措施将查询性能提高10%,则应将精力集中在2%上。如果您是Google,查询性能的2%会带来20亿美元的额外硬件负担,那么无论如何它都需要进行优化。
| 归档时间: |
|
| 查看次数: |
2963 次 |
| 最近记录: |