[英]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.