数据库表优化连接与重复列

Ath*_*ion 1 sql database-design query-optimization

这更像是一种偏好,但我想知道人们认为什么是最佳选择.我有一个问题,答案和点(因为我需要跟踪哪个用户指出了这一点)

表转储

Question:
  id
  title

Answer:
  id
  question_id
  user_id
  response

Point_Answer:
  id
  answer_id
  user_id
  points
Run Code Online (Sandbox Code Playgroud)

因此,在此布局中获取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
Run Code Online (Sandbox Code Playgroud)

如果我这样改变它:

Question:
  id
  title

Answer:
  id
  question_id
  user_id
  response
  points

Point_Answer:
  id
  answer_id
  user_id
  points
Run Code Online (Sandbox Code Playgroud)

查询的负担会减轻

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
Run Code Online (Sandbox Code Playgroud)

也意味着我必须确保添加Point_Answer时添加Answer.points.所以基本上是一个额外的更新.基本上它是"完整性与冗余"和一些优化,更好的方法是什么?

HLG*_*GEM 5

这将取决于第一个不是连接的复杂性有多慢.完全这样做是一个非常糟糕的主意,因为你不想写(一次)更复杂的查询.表现是做这种性质的唯一真正原因.

如果第一个是慢得令人无法接受的,那么对这些点求和的表或字段可以是可接受的非规范化,只要你通过触发器而不是从应用程序保持字段更新(这是确保非规范化数字准确性的唯一方法).您需要测试解决方案,包括额外的更新时间,以确定您是否确实节省了任何处理时间.这可能取决于数字的更改频率.如果你在更新时添加一秒并在select上保存十秒,那么实例,但每个selct你有10,000次更新,这不是一个好的优化.但是,如果您将报告从一小时到几毫秒,并且只在插入或更新中添加毫秒,则可能是可接受的.

如果没有实际编码和测试具有生产级工作负载和数据的两个解决方案,就无法回答这个问题.