繁体   English   中英

MySQL - 如何优化查询以计算投票数

[英]MySQL - how to optimize query to count votes

在听取了关于实现以下结果的最佳方法的一些意见之后:

我想在我的MySQL数据库中存储可以由用户投票的产品(每个投票值+1)。 我还希望能够看到用户投票的总次数。

简单来说,下表结构是理想的:

  table: product          table: user            table: user_product_vote       
+----+-------------+    +----+-------------+    +----+------------+---------+ 
| id |   product   |    | id | username    |    | id | product_id | user_id |
+----+-------------+    +----+-------------+    +----+------------+---------+
| 1  | bananas     |    | 1  | matthew     |    | 1  | 1          | 2       |
| 2  | apples      |    | 2  | mark        |    | 2  | 2          | 2       |
| .. | ..          |    | .. | ..          |    | .. | ..         | ..      |

这样我就可以为每个产品或用户执行一个COUNT的user_product_vote表。

例如,当我想查找香蕉和在网页上显示的投票数时,我可以执行以下查询:

SELECT p.product AS product, COUNT( v.id ) as votes
FROM product p
LEFT JOIN user_product_vote v ON p.id = v.product_id
WHERE p.id =1

如果我的网站变得非常成功(我们都可以梦想)并且我有成千上万的用户在数千种产品上投票,我担心在每个页面视图中执行这样的COUNT在服务器资源方面效率非常低。

更简单的方法是在产品表中创建一个“投票”列,每次添加投票时都会增加。

  table: product               
+----+-------------+-------+
| id |   product   | votes |
+----+-------------+-------+
| 1  | bananas     | 2     |
| 2  | apples      | 5     |
| .. | ..          | ..    |

虽然这更加资源友好 - 但我丢失了数据(例如,由于没有他们的投票活动记录,我不能再阻止某人投票两次)。

我的问题是:
i)我是否过度担心服务器资源,应该坚持使用三个表选项? (即我是否需要更加相信数据库处理大型查询的能力)
ii)是他们在不丢失信息的情况下实现结果的更有效方式

您永远不会过度担心资源,当您第一次开始构建应用程序时,您应始终考虑资源,空间,速度等,如果您的网站流量急剧增长而您从未构建过资源,那么您就会开始遇到问题。

至于投票制度,我个人会像这样保留投票:

table: product          table: user             table: user_product_vote       
+----+-------------+    +----+-------------+    +----+------------+---------+ 
| id |   product   |    | id | username    |    | id | product_id | user_id |
+----+-------------+    +----+-------------+    +----+------------+---------+
| 1  | bananas     |    | 1  | matthew     |    | 1  | 1          | 2       |
| 2  | apples      |    | 2  | mark        |    | 2  | 2          | 2       |
| .. | ..          |    | .. | ..          |    | .. | ..         | ..      |

原因:

首先, user_product_vote不包含文本,blob等,它纯粹是整数,因此无论如何它占用的资源更少。

其次,您可以在应用程序中找到更多通向新实体的门户,例如过去24小时的总投票数,过去24小时内的最高评分产品等。

以这个例子为例:

table: user_product_vote       
+----+------------+---------+-----------+------+ 
| id | product_id | user_id | vote_type | time |
+----+------------+---------+-----------+------+
| 1  | 1          | 2       | product   |224.. |
| 2  | 2          | 2       | page      |218.. |
| .. | ..         | ..      | ..        | ..   |

一个简单的查询:

SELECT COUNT(id) as total FROM user_product_vote WHERE vote_type = 'product' AND time BETWEEN(....) ORDER BY time DESC LIMIT 20

另一件事是,如果用户在1AM 1点投票,然后在下午2PM再次尝试投票,您可以轻松检查他们上次投票的时间以及是否应该再次投票。

如果您坚持使用增量示例,那么您将失去很多机会。


关于你的count() ,无论你如何优化你的查询,它都不会在很大程度上产生影响。

使用极大的用户群,您可以从不同的角度查看资源使用情况,例如负载均衡器,主要是服务器设置,Apache,捕获等等,您只能对查询做很多事情。

如果我的网站变得非常成功(我们都可以梦想)并且我有成千上万的用户在数千种产品上投票,我担心在每个页面视图中执行这样的COUNT在服务器资源方面效率非常低。

不要浪费你的时间来解决想象中的问题。 mysql完全能够在几分之一秒内处理数千条记录 - 这就是数据库的用途。 清晰简单的数据库和代码结构远比没有人需要的神秘“优化”重要得多。

为什么不混合搭配? 只需在产品和用户表中有最终计数,这样您就不必每次都计算并拥有投票表,这样就没有双重发布。

编辑:为了进一步解释,产品和用户表将有一个名为“投票”的列。 每次在user_product_vote中成功插入时,都会增加相关的用户和产品记录。 这样可以避免欺骗投票,并且您不必每次都运行复杂的计数查询。

编辑:另外我假设你已经在product_id和user_id上创建了一个唯一索引,在这种情况下,任何重复尝试都会自动失败,你不必在插入之前检查表。 您只需要确保插入查询已运行,​​并且您在insert_id上的表单中获得了“id”的有效值

您必须平衡您的网站快速执行的愿望(其中第二个架构最好)和为特定用户计算投票的能力并防止双重投票(我将选择第一个架构)。 因为你只对user_product_vote表使用整数列,所以我看不出性能如何受到太大影响。 多对多关系很常见,因为您已使用user_product_vote实现。 如果你确实想为特定用户计算投票并防止双重投票,那么user_product_vote是我能想到实现它的唯一clean方式,因为任何其他方式都可能导致稀疏记录,重复记录和各种坏事。

每次有人投票时,您都不希望直接使用聚合更新产品表 - 这将锁定产品行,这将影响正在使用产品的其他查询。

假设并非所有产品查询都需要包含投票列,您可以保留一个单独的产品投票表来保留运行总计,并将您的userproductvote表作为一种方法来强制执行每个产品业务规则/审核的用户投票。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM