mySQL效率问题 - 如何找到正常化的正确平衡......?

Foo*_*Foo 6 mysql performance normalization

我很擅长使用关系数据库,但已阅读了一些书籍并了解了良好设计的基础知识.

我正面临一个设计决定,我不知道如何继续.这是我正在构建的一个非常简化的版本:人们可以对照片进行评分1-5,我需要在跟踪个人投票的同时显示图片上的平均投票.例如,12人投票1人,7人投票2人等.等等.

我的规范化怪胎最初设计了这样的表结构:

Table pictures
id* | picture | userID | 

Table ratings
id* | pictureID | userID | rating
Run Code Online (Sandbox Code Playgroud)

随着所有外键约束和所有设置,因为他们应该是.每当有人对图片进行评分时,我只需在评分中添加一条新记录即可.

要查找图片的平均评分,我只需运行以下内容:

SELECT AVG(rating) FROM ratings WHERE pictureID = '5' GROUP by pictureID 
Run Code Online (Sandbox Code Playgroud)

以这种方式设置它让我运行我的花哨的统计数据.我很容易找到谁将某张照片评为3,哪些不是.

现在我在想是否有一堆评级(这在我真正的设计中是非常可能的),找到平均值将变得非常昂贵和痛苦.

使用非规范化版本似乎更有效.例如:

Table picture
id | picture | userID | ratingOne | ratingTwo | ratingThree | ratingFour | ratingFive
Run Code Online (Sandbox Code Playgroud)

要计算平均值,我只需要选择一行.它似乎更有效率,但更加丑陋.

有人能指出我做正确的方向吗?我最初的研究表明,我必须"找到合适的平衡点",但我该如何找到平衡点呢?任何文章或其他阅读信息也将受到赞赏.

谢谢.

lex*_*exu 4

您的规范化方法很有意义,而非规范化方法则不然。


根据我的经验(电信绩效管理,每 1/4 小时数十万个数据点),我们将执行以下操作:

Table: pictures
id* | picture | userID | avg_rating | rating_count

Table: ratings
id* | pictureID | userID | rating
Run Code Online (Sandbox Code Playgroud)

对于电信公司,图片评级将每天重新计算一次,您应该定期(例如每小时)或每次插入时进行计算(重新计算评级的图片,而不是整个表格)。这取决于您获得的评分数量。


在电信公司中,我们还将评级日期保留在“图片”表中,并在评级表中保留 1/4 小时时间戳,但我认为您不需要那么详细。


“非规范化”是将可计算的事实(计数(评级)和平均值(评级))移至图片表。这可以节省 CPU 周期,但会消耗更多存储空间。