mysql计票优化
所以,我做了一个文件中心,没有什么大的或花哨的,只是为了存储一些可能被其他人共享下载的文件。我突然想到,我最初打算计算上升票或下降票的数量。查询可能是服务器繁重的mysql计票优化,mysql,database,database-design,Mysql,Database,Database Design,所以,我做了一个文件中心,没有什么大的或花哨的,只是为了存储一些可能被其他人共享下载的文件。我突然想到,我最初打算计算上升票或下降票的数量。查询可能是服务器繁重的 select*from files; 在这种情况下,我将收到一个文件数组,我可以循环,现在可以获得每个文件的细节,包括投票一个文件,相同的foreach循环将包括一个进一步的查询,该查询将获得计数,一个文件将获得where子句中的文件id,如下所示 select*from votes where upvoted=true and f
select*from files;
在这种情况下,我将收到一个文件数组,我可以循环,现在可以获得每个文件的细节,包括投票一个文件,相同的foreach循环将包括一个进一步的查询,该查询将获得计数,一个文件将获得where子句中的文件id,如下所示
select*from votes where upvoted=true and file.id=?
我正在考虑使用pdo::rowCount来获得我的答案。现在,我身体里的每一根骨头都说这很糟糕,想象一下,我收到了10000个文件,我只是对每个文件进行了10000个额外的查询,我还没有查看投票结果,我认为投票结果可能会类似。这里的任何优化建议都只是几个表结构的一个小代表。如果你愿意的话,向上和向下投票的哥伦布都是布尔型或tinyint型
table: file table: user table: votes
+----+-------------+ +----+-------------+ +--------+--------+--------+--------+
| id |storedname | | id | username | |file_id | user_id| upvoted | downvoted
+----+-------------+ +----+-------------+ +--------+--------+--------+--------+
| 1 | 45tfvb.txt | | 1 | matthew | | 1 | 2 | 1 | 0
| 2 |jj7fnfddf.pdf| | 2 | mark | | 2 | 1 | 1 | 1
| .. | .. | | .. | .. | | .. | .. | .. | ..
两个建议:
避免选择*,尤其是当你要数数的时候。用类似的东西替换它:
SELECT COUNT(1) AS total WHERE upvoted=true AND file.id=?
也许您想创建一个触发器来保持文件表中计数器的更新
我希望它能对你有所帮助。有两种方法可以做到这一点。更快地完成此任务的更好方法是编写单独的查询,并在编程语言(如php、python)中构建一个变量。。等等
SELECT
d.id as doc_id,
COUNT(v.document_id) as num_upvotes
FROM votes v
JOIN document d on d.id = v.document_id
WHERE v.upvoted IS TRUE
GROUP BY doc_id
);
这将返回您的已升级文档列表。你也可以为你的反对票做同样的事情
然后,在您从文档中选择之后,执行for循环,按ID将投票与文档进行比较,并构建到字典或列表中
第二种方法是在select语句中添加子查询选择,这种方法在运行时可能需要更长的时间(如果表中有一堆记录),效率较低,但更容易编写
SELECT
logical_name ,
document.id ,
file_type ,
physical_name ,
uploader_notes ,
views ,
downloads ,
user.name ,
category.name AS category_name,
(Select count(1) from votes where upvoted=true and document_id=document.id )as upvoted,
(select count(1) from votes where upvoted=false and document_id=document.id) as downvoted
FROM document
INNER JOIN category ON document.category_id = category.id
INNER JOIN user ON document.uploader_id = user.id
ORDER BY category.id
为什么会有一个for循环来执行这样的额外查询?为什么不使用文件数据进行选择并将投票表加入其中?然后再做一个for循环来循环。同时,从中选择也是一个坏习惯。。如果您需要更具体的东西,请指定。。。这会让事情变得更顺利faster@JohnRuddellselect*不是我真正的查询,我只是想简化一下。在我运行查询之前,我没有file.id部分。这里是实际的“获取所有文件”查询,如果它有助于选择逻辑名称、文件类型、物理名称、上载者注释、视图、下载、user.name、,category.name AS category\u name FROM document internal JOIN category ON document.category\u id=category.id internal JOIN user ON document.uploader\u id=user.id ORDER BY category.id减去对投票表的任何引用,但投票表如我所示。好,但您正在拉出一个列表表中id为的文件的数目,对吗?我想我的意思是,为什么不在fileID INSELECT ID FROM FILE的投票中选择*呢。。。不同的变化。。但您应该能够从一个select for VOUTES表中获得所需的一切,然后使用for循环匹配到您的文件select。。而不是在for中进行数千次选择loop@JohnRuddell是的,子查询似乎是我想要的,让我检查一下如何将其转换到当前的查询中。提到触发器听起来也是一个合理的解决方案,我也将对此进行研究。有可能对子查询进行计数并将其作为列返回吗?对不起,我无法发表评论,但我需要更多的声誉才能这样做。而且,是的,您可以在每次投票插入或更新中更新文件列,以使计算字段保持最新。对数据库进行数千次查询要比执行一次对表进行数千次比较的查询慢得多鲁德尔,看看你们能否遵循我混乱的逻辑,我需要的是和你们所说的相反的东西。我需要从文件表中选择许多列,这些列内部与其他表连接,我还需要获得指定文件id的投票,这些文件id是我从前面提到的或外部查询中获得的,如果你愿意,那么你想从文件表中拉出多个列。。。该文件表已连接到其他两个表,对吗?然后你想对这些文件进行上下票数统计?向上和向下的投票是否存储在类别表中?很好,您有它,没有,向上和向下的投票以我在问题中所说明的确切方式存储在单独的表中。我知道如果它们存储在categories表中,我可以使用内部连接,一切都会很好,但它们存储在seprate表中。我曾经尝试过简单地通过左联接将投票表添加到联接中,但效果不太好,所以您希望您的上下投票不在第一个选择中加入到表中?