这更像是一种偏好,但我想知道人们认为什么是最佳选择。我有一个问题,答案和点(因为我需要跟踪哪个用户指出了这一点)
表转储
Question:
id
title
Answer:
id
question_id
user_id
response
Point_Answer:
id
answer_id
user_id
points
因此,在此布局中获取Top Answer将需要复杂的连接序列。
SELECT t2.id, t2.user_id, t2.response, MAX(points)
FROM Question as t1,
(SELECT qa.*, SUM(pa.points) as points
FROM answer as qa, Point_Answer as pa
WHERE qa.id = pa.answer_id
GROUP BY qa.id) as t2
WHERE t1.id = %s AND t1.id = t2.question_id
如果我这样改变它的地方:
Question:
id
title
Answer:
id
question_id
user_id
response
points
Point_Answer:
id
answer_id
user_id
points
查询将减少负担
SELECT A.id, A.user_id, A.response, MAX(points)
FROM Question as Q, Answer as A
WHERE Q.id = %s AND Q.id = A.question_id
GROUP BY A.id
也意味着我必须确保添加Point_Answer时添加Answer.points。所以基本上是一个额外的更新。基本上它是“完整性与冗余”和一些优化,更好的方法是什么?
答案 0 :(得分:5)
这取决于第一个不是连接的复杂性有多慢。完全这样做是一个非常糟糕的主意,因为你不想写(一次)更复杂的查询。表现是做这种性质的唯一真正原因。
如果第一个是慢得令人无法接受的话,那么对这些点求和的表或字段可以是可接受的非规范化,只要你通过触发器而不是从应用程序保持字段更新(唯一的方法是确保非规范化数字的准确性) )。您需要测试解决方案,包括额外的更新时间,以确定您是否确实节省了任何处理时间。这可能取决于数字的更改频率。如果你在更新时添加一秒并在select上保存十秒,那么实例,但每个selct你有10,000次更新,这不是一个好的优化。但是,如果您将报告从一小时到几毫秒,并且只在插入或更新中添加毫秒,则可能是可接受的。
如果没有实际编码和测试具有生产级工作负载和数据的解决方案,就无法回答这个问题。
答案 1 :(得分:2)
这取决于很多因素,其中大多数因素取决于您的设置。
两个最重要的因素是:
基本上,我会坚持第一个解决方案。没有规范化的关系方案有时是一件好事,但你应该对结构进行非规范化处理,如果你确定的话,它会给你带来性能提升,如果你已经在生产环境中发现应用程序的瓶颈。
答案 2 :(得分:1)
如果查询表现得相当好,我会保持原样。在我的书中,一个丑陋,表现良好的查询超过了冗余。
使用冗余选项,您需要确保将更新语句封装在事务中以确保所有内容都得到更新;否则,您将面临使数据不同步的风险。
我使用了一些遗留应用程序,这些应用程序在没有事务的情况下进行了冗余路由,当一个表因任何原因没有得到更新时,它会变得混乱。