【问题标题】:Optimizing multiple SELECTs优化多个 SELECT
【发布时间】:2011-10-18 04:48:48
【问题描述】:
SELECT 
  (SELECT COUNT(*) FROM votes WHERE votes.vote = 1) AS upvotes,
  (SELECT COUNT(*) FROM votes WHERE votes.vote = -1) AS downvotes,
FROM votes WHERE link = <linkid>

直截了当的问题;如何优化?我想不出更好的方法,但我不擅长 MySQL。

感谢您的回复!

编辑:为了清楚起见:我希望它返回一行两列; upvotesdownvotes

【问题讨论】:

  • 这还能给你想要的结果吗?
  • 错误,是的,我认为是的。我根据我在代码中使用的查询改编了该查询。
  • @MarkByers 我确定不是!
  • 这个查询需要子查询的where子句。

标签: mysql sql optimization select


【解决方案1】:
SELECT sum(case when vote = 1 then 1 end) as upvotes,
    sum(case when vote = -1 then 1 end) as downvotes
FROM votes
WHERE link = < linkid >

【讨论】:

    【解决方案2】:

    尝试使用 SUM 而不是 COUNT:

    SELECT 
      SUM(vote = 1) AS upvotes,
      SUM(vote = -1) AS downvotes
    FROM votes WHERE link = <linkid>
    

    请注意,这不会给您提供与您发布的查询相同的结果。我认为您发布的查询是错误

    【讨论】:

    • 等等,然后我的查询会做什么?你是做什么的?
    • @Jonathan:您的查询给出了总票数或正面 (vote=1) 和负面 (vote=-1) 票,计算表的所有行。这里给出的所有答案,只计算那些行的正票和负票 link=&lt;linkid&gt;
    【解决方案3】:

    我会用这个:

    SELECT COUNT(*), vote AS numvotes FROM votes WHERE vote = -1 OR vote = 1 GROUP BY vote
    

    【讨论】:

    • 聪明!忘了它,thnx @MattFenwick
    • 这是不同的——两行。
    • 这不会以 OP 期望的方式返回结果。 OP 需要两列:一列用于赞成票,另一列用于反对票。您的查询将返回 0、1 或 2 行,具体取决于现有数据。
    • 它有所不同,但它可能比其他选项更快(或更慢)。更改应用程序代码或查询以以相同格式显示结果并不难。
    【解决方案4】:
    SELECT 
      COUNT(case vote when  1 then 1 else null end) AS upvotes,
      COUNT(case vote when -1 then 1 else null end) AS downvotes
    FROM votes WHERE link = <linkid>
    

    学习时间:count 只计算非空值,因此无论何时您看到 then 1 都可能是 then 'Yay!'。不计算空值。

    【讨论】:

      【解决方案5】:

      恕我直言,您根本不应该计算总票数。相反,您应该将总投票数与项目一起存储,并使用详细的投票日志作为确保结果完整性并让用户能够撤回投票的工具。

      【讨论】:

      • @Hogan:从不是一个非常强烈的词。选举结束后,我不希望我的查询一次又一次地计算所有选票,每次用户想要查看结果时。相反,重复的聚合数据并不总是坏事(尤其是当它们不会改变时 - 或者有时需要超高速但没有 100% 准确度)
      • 我怀疑每次我访问奥巴马的 Twitter 页面时,它都会运行一个有 10,000,000 名追随者的查询……或 YouTube 的浏览量……等等。
      • 假设您有 1 个用户可以对 1 个项目投 1 票,如果有 1000 个用户对 1000 个项目投票(这将是一个低活跃度论坛),您将生成 100 万个条目.并且在每个页面视图中,您都会对它们进行过滤和求和......很可能每页多次。数据重复优化,不兼容。
      • @ypercube(和 Thilo)——缓存不同于复制。 teresko 不建议添加新数据点(选举结果) teresko 建议您保留总数并验证它(一些时间/时间段。)。似乎是一个糟糕的计划。
      • @Hogan ,是的,当用户被删除时,他的投票也应该被删除。这是一种情况,当您重新计算总票数时(或者更有可能:计算该用户的投票并将其从 total 中删除)。还有其他类似的情况。
      【解决方案6】:

      我猜所有评论者的意思是你的查询应该是:

      SELECT 
        (SELECT COUNT(*) FROM votes WHERE link = <linkid> AND vote = 1 ) AS upvotes,
        (SELECT COUNT(*) FROM votes WHERE link = <linkid> AND vote = -1) AS downvotes
      

      到目前为止,您至少有 4 种其他方式与此方式相同(3 种方式完全相同,1 种方式略有不同,给出相同的结果,但在 2 行中)。使用您的数据进行测试并选择较快的数据(或保留所有数据并稍后在表格变大时再次测试)。

      (link,vote) 上的复合索引也适用于所有版本。

      【讨论】:

        猜你喜欢
        • 2011-12-21
        • 2017-01-10
        • 1970-01-01
        • 2023-03-23
        • 2016-07-27
        • 2011-12-01
        • 2013-01-03
        • 1970-01-01
        • 2019-09-03
        相关资源
        最近更新 更多