mysql计数投票优化

时间:2014-03-10 15:00:16

标签: mysql database database-design

所以我制作一个文件中心没什么大不了或只是为了存储一些可能被他人共享下载的文件。它只是发生在我原本打算计算upvotes或downvotes的数量的方式,查询可能是服务器重。查询获取文件是

select*from files;

并且在这样的情况下我会收到我的文件数组,我可以循环并获得每个文件的详细信息现在包含投票文件,相同的foreach循环将包括另一个查询,将获得计数的数量投票一个文件会得到(where子句中的文件id),如此

select*from votes where upvoted=true and file.id=?

我正在考虑使用pdo :: rowCount来获取答案。现在evey骨头在我的身体里只是说这是非常糟糕的,因为想象我得到10,000个文件我只是在每个文件上运行了10,000个额外的查询,而我还没有看到我认为可能会出现类似情况的downvotes。这里的任何优化建议都是几个表结构的小代表。如果你愿意的话,upvoted和downvoted columbs的类型为bool或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
| .. | ..          |    | .. | ..          | | ..     |  ..    |    ..  |      ..

2 个答案:

答案 0 :(得分:1)

两个建议:

  1. 特别是如果你要计算的话,请避免SELECT *。用这样的东西替换它:

    SELECT COUNT(1) AS total WHERE upvoted=true AND file.id=?
    
  2. 也许你想创建一个TRIGGER来保持更新 file 表中的计数器。

  3. 我希望它对你有帮助。

答案 1 :(得分:1)

有两种方法可以做到这一点。更好的方法(更快)是编写单独的查询并在编程语言中构建一个变量(如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
);

将返回您的upvoted文档列表。你可以为你的downvotes做同样的事。

然后在您从文档中选择后,执行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