【问题标题】:MySQL: SELECT(x) WHERE vs COUNT WHERE?MySQL:选择(x)在哪里与在哪里计算?
【发布时间】:2011-01-19 06:51:58
【问题描述】:

这将是其中一个问题,但我需要问它。

我有一张大桌子,可能有也可能没有一个唯一的行。因此,我需要一个 MySQL 查询,它只会告诉我 TRUE 或 FALSE。

以我目前的知识,我看到两个选项(伪代码):

[id = 主键]

选项 1:

SELECT id FROM table WHERE x=1 LIMIT 1
... and then determine in PHP whether a result was returned.

选项 2:

SELECT COUNT(id) FROM table WHERE x=1
... and then just use the count.

出于某种原因,这两种方法中的哪一种更可取,还是有更好的解决方案?

谢谢。

【问题讨论】:

    标签: mysql performance select count


    【解决方案1】:

    AFAIK,如果您在 ID 列上有索引,则两个查询的性能或多或少都相同。第二个查询将在您的程序中减少 1 行代码,但这也不会对性能产生任何影响。

    【讨论】:

    • ID 列上的索引在这里无关紧要,OP 想要 X 上的索引。
    【解决方案2】:

    如果选择标准是真正独特的(即最多产生一个结果),那么通过在该标准所涉及的一列(或多列)上建立索引,您将看到性能大幅提升。

    create index my_unique_index on table(x)
    

    如果你想强制唯一性,那甚至不是一个选项,你必须有

    create unique index my_unique_index on table(x)
    

    有了这个索引,对唯一标准的查询将执行得非常好,而不管像 count(*)、count(id)、count(x)、limit 1 等小的 SQL 调整。 为了清楚起见,我会写

    select count(*) from table where x = ?
    

    出于另外两个原因,我会避免使用 LIMIT 1:

    • 这是非标准 SQL。我对此不感兴趣,在必要时使用 MySQL 特定的东西(即用于分页数据),但这里没有必要。
    • 如果由于某种原因,您有不止一行数据,这可能是您的应用程序中的一个严重错误。使用 LIMIT 1,您将永远看不到问题所在。这就像在《侏罗纪公园》中计算恐龙的数量,并假设数量只会下降。

    【讨论】:

    • 侏罗纪公园类比+1。我可能会偷那个。对于其余的论点没有赞成票 - 我完全同意。
    • 感谢您的回答,尽管我确实喜欢使用 LIMIT 1。非标准 SQL 不会打扰我(只要它有效),至于第二个参数,在我的应用几乎就像恐龙复活一样神奇。 :)
    【解决方案3】:

    通常,您使用group by having 子句确定表中是否存在重复行。如果您有一个带有 id 和名称的表。 (假设 id 是主键,你想知道 name 是唯一的还是重复的)。你会使用

    select name, count(*) as total from mytable group by name having total > 1;
    

    上面会返回名字重复的次数和次数。

    如果您只想通过一个查询来得到答案为真或假,您可以使用嵌套查询,例如

    select if(count(*) >= 1, True, False) from (select name, count(*) as total from mytable group by name having total > 1) a;
    

    如果您的表有重复的行,上述内容应返回 true,否则返回 false。

    【讨论】:

    • 由于他在做 LIMIT 1,我怀疑 OP 是否在寻找重复项。
    【解决方案4】:

    就我个人而言,我通常会先从行中选择 id 并限制为 1 行。从编码的角度来看,我更喜欢这个。我不必实际检索数据,只需检查返回的行数。

    如果我要比较速度,我会说不在 MySQL 中进行计数会更快。我没有任何证据,但我的猜测是 MySQL 必须获取所有行,然后计算有多少行。不过……再想一想,它也必须在第一个选项中这样做,这样代码也会知道有多少行。但既然你有COUNT(id) vs COUNT(*),我会说might be slightly slower

    【讨论】:

      【解决方案5】:

      直观地说,第一个可能更快,因为它可以在找到第一个值时中止表(或索引)扫描。但是您应该检索 x 而不是 id,因为如果引擎使用 x 上的索引,则不需要转到该行实际所在的块。

      另一种选择可能是:

      select exists(select 1 from mytable where x = ?) from dual
      

      这已经返回一个布尔值。

      【讨论】:

        猜你喜欢
        • 2013-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-03
        • 1970-01-01
        • 1970-01-01
        • 2015-10-24
        相关资源
        最近更新 更多