哪个是最有效的SELECT方法,为什么?

时间:2013-03-08 10:02:14

标签: mysql sql

考虑一个人们以他们喜欢的颜色投票(+1)或减少(-1)的网站,我有两张桌子:

一个列出了人们可以投票的所有颜色,第二个表记录了每个投票的颜色,颜色是什么颜色以及是+1还是-1。

关于获取特定颜色的聚合投票,是否更有效包括颜色表上的总分数以及当一个人投票时有插入语句和更新语句:

INSERT INTO votes (colour,vote) VALUES (red,-1);
UPDATE colours SET score=score-1 WHERE colour='red';

SELECT score FROM colours WHERE colour='red';

或者在投票时只有一个INSERT语句,然后获取你的分数会更有效率;

SELECT SUM(vote) AS score FROM votes WHERE colour='red';

我猜当投票数量非常少时,选项#2最好,但当投票表非常大时,选项#1会变得更好吗?

是否有一些工具可用于根据表格大小等对某些SQL查询进行排序?

4 个答案:

答案 0 :(得分:4)

我个人认为,如果你想显示一个总分(我想你想要经常显示得分),那么随着投票表中行数的增加,你会发现聚合{ {1}}查询将花费更长时间,而且不能很好地扩展。

此外,如果您计划实现仅显示分数为100或更高的颜色的查询,那么使用聚合将使查询更简单快捷。

使用得分列的另一个好处是,如果在将来某个日期你要清除SUM表(例如,如果它变得太大),那么你可以这样做而不会失去颜色分数。

我认为这不是过早的优化,我认为这是设计一个考虑到规模的系统,所以我要做的是创建一些实际数量的投票,颜色和每分钟查询的样本数据集' d期望并运行一些性能测试来评估什么是更好的方法,因为现在选择正确的方法更容易(阅读更便宜)而不是在事情出现问题时修复它。

答案 1 :(得分:1)

两个查询之间的性能差异微不足道。您应该根据要保留的信息确定结构。

如果您只需要总分,请使用

UPDATE colours SET score=score-1 WHERE colour='red';

这将非常快,因为表colours只会有几行。

另一方面,可能有理由存储每个用户的投票(例如确保他们不投票两次)。在这种情况下,为每次投票插入一行。

INSERT INTO votes (colour,vote,user_id) VALUES (red,-1);

但是,不要因为你认为它会更快而创建一个不必要行的结构。

答案 2 :(得分:0)

您是否过早优化或这是一个真正的问题?

第一种方法可能会更快,但为了优化,您需要更改域模型。只要您知道自己在做什么以及它给您带来了哪些不利之处(可能需要在所有使用投票的地方更新两个表,导致错误同步),这是可以的。

但你可能会考虑其他选择。例如,如果颜色数量不是那么大,您可以为其评级构建缓存。这将保持简单的模型,简单的评级机制,并提供您所需的速度,减去一些记忆;)

答案 3 :(得分:0)

此类优化的关键是您要优化的。存储总和会使插入/删除/更新花费更长时间。计算总和会影响数据查询的性能。

如果您正在删除或更新数据,您很快就会看到预先计算总和的愚蠢行为。当您认为只更改数据时,对数据的任何此类更改都需要修改多个记录。

但是,您的结构似乎只有插入 - 顺便说一下,这是一个很好的设计选择,因为您可以看到每一个变化。在这种情况下,问题是您是否要在每个插入上花费开销,或者您想要“报告”方面的开销。在某些情况下,这个问题很容易。

如果您每次要查看总和时有1000票,请动态计算总和。如果每次投票都有1000个总和,那么存储总和看起来就像是更有效的方法。

我的猜测是工作负荷介于极端之间。我的自然偏见是将数据存储为生成的数据,然后为摘要和报告添加其他表。我建议采用以下两种方法之一:

(1)仅保留交易数据并即时计算总和。排列表格上的索引,使总和尽可能高效。

(2)仅将事务保留在一个表中并计算另一个表中的总和(使用触发器或存储过程)。这为您提供了大多数用途所需的最新值。插入应该比在每条记录上存储总和更有效(因为用户级别的表小于投票级别的表)。

您对计算投票记录中的金额的建议通常不会是我考虑的选项。当你需要增量投票的历史时,这将是可取的。但是,如果您正在查看历史记录,那么执行sum计算或计算应用程序层中的总和也是可行的替代方案。