如何提高投票系统的性能?
我有一个带有投票系统的网站(喜欢/不喜欢)。
该应用程序已由另一位开发人员开发,现在网站越来越大,性能受到认真考虑。
我有下表:
CREATE TABLE `vote` (
`id` int(11) NOT NULL auto_increment,
`article_id` int(11) NOT NULL,
`token` varchar(64) collate utf8_unicode_ci NOT NULL,
`type` int(1) NOT NULL,
PRIMARY KEY (`id`),
KEY `article_id` (`article_id`)
) ENGINE=InnoDB;
令牌列用于标识每个用户/投票/日期,它是一个唯一的令牌,是用户指纹的一部分,允许他们投票一次并更改其投票类型。
最慢的查询之一如下:
SELECT count(*) AS `nb` FROM `vote` WHERE (token = '00123456789012345678901234567890');
当服务器未关闭时,有时需要近 10 秒才能返回。
我不能在这里使用缓存,因为我需要实时检查以允许或不允许投票并增加计数。
我无法更改太多应用程序逻辑,因为它依赖于应用程序中各处使用的太多依赖项(设计得很糟糕)。
因此,我正在寻找提高性能的选项,即使是一些性能。
编辑:我在令牌列上有一个索引
,大约有 2,000,000 行,并且所有令牌几乎都是唯一的
编辑:
我根据您的所有建议运行了基准测试:
Top average queries
1. SELECT COUNT(*) AS nb FROM `vote` WHERE (`token` = '%s') completed in 2.19790604115 sec
2. SELECT COUNT(`id`) AS nb FROM `vote` WHERE (`token` = '%s') completed in 2.28792096376 sec
3. SELECT COUNT(`id`) AS nb FROM `vote` WHERE (`token` = '%s') GROUP BY `token` completed in 2.3732401371 sec
4. SELECT COUNT(*) AS nb FROM `vote` WHERE (`token` = '%s') GROUP BY `token` completed in 2.57634830475 sec
有时是第三个查询是最快的,但有时也是最差的。
我运行了 10 次,其中每个查询运行了 20 次
,我运行这个基准没有任何索引(id
上的索引除外),
这很奇怪,我认为 COUNT(id) 会加快了查询速度。
I've a website with a voting system (like/dislike).
The application has been developed by another developer, and now the website is getting bigger and bigger and performance is serious consideration.
i've the following table :
CREATE TABLE `vote` (
`id` int(11) NOT NULL auto_increment,
`article_id` int(11) NOT NULL,
`token` varchar(64) collate utf8_unicode_ci NOT NULL,
`type` int(1) NOT NULL,
PRIMARY KEY (`id`),
KEY `article_id` (`article_id`)
) ENGINE=InnoDB;
The token column is used to identify each user/vote/date it is an unique token which is part of a user fingerprint to allow them to vote once and change their vote type.
One of the most slow query is the following:
SELECT count(*) AS `nb` FROM `vote` WHERE (token = '00123456789012345678901234567890');
It sometimes takes almost 10seconds to return when the server doesn't shutdown.
I can't use a cache here, because I need to check in a real time to allow or not the vote and increment the count.
I cannot change much application logic because it relies on too much dependancies used everywhere in the application (it was badly designed).
So I'm looking for options to improve, even a few, performance.
Edit: I've an index on token column
there are ~2,000,000 rows and all token are almost unique
EDIT:
I ran a benchmark with all your advises :
Top average queries
1. SELECT COUNT(*) AS nb FROM `vote` WHERE (`token` = '%s') completed in 2.19790604115 sec
2. SELECT COUNT(`id`) AS nb FROM `vote` WHERE (`token` = '%s') completed in 2.28792096376 sec
3. SELECT COUNT(`id`) AS nb FROM `vote` WHERE (`token` = '%s') GROUP BY `token` completed in 2.3732401371 sec
4. SELECT COUNT(*) AS nb FROM `vote` WHERE (`token` = '%s') GROUP BY `token` completed in 2.57634830475 sec
Sometimes the third query is the quickest but sometimes it's the worst.
I ran it 10 times where each query is run 20 times
I ran this benchmark WITHOUT any INDEXES (except one on id
)
That's weird, I though the COUNT(id) would have speed up a bit the query.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果尚未对标记列建立索引,您应该考虑对其进行索引。
You should look at indexing the token column, if it isn't already indexed.
听起来您应该创建一个存储汇总数据的表。这样,查询不需要每次都进行完整计数,而只需从上次求和开始进行计数。 (根据您的完整系统,如果行永远不会被删除,您可能会有一个与以下非常相似的表)
然后,当您将一行插入投票时,您也可以调用
It sounds like you should create an table that stores the summed data. This way the query doesn't need to do a full count each time but just a count from the last time it was summed. (Depending on your full system and if rows are never deleted you could have a table very similar to the follow)
Then when you insert a row into vote you can also call
一般来说,您应该为大型表中经常运行的查询的 where 子句中使用的列添加索引。在您的示例查询中,您需要在标记列上添加一个。看起来您正在使用 MySQL 数据库,因此这是该数据库的创建表语句的重要部分:
In general, you should add indexes for columns in large tables that are used in where clauses of queries that are run often. In your example query, you'd need one on the token column. It looks like you are using MySQL database, so here's the important part of the create table statement for that database:
我并没有真正关注您当前的实现,但是我对 99.99% 的投票系统使用的以下方法非常高效:
结果:
完整脚本:
希望它有所帮助: )
I havent really paid too much attention to your current implementation but the following method I use for 99.99% of voting systems is extremely performant:
Results:
Full script:
Hope it helps :)