代码之家  ›  专栏  ›  技术社区  ›  Tom

MySQL:选择(X)何处与计数何处?

  •  2
  • Tom  · 技术社区  · 15 年前

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

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

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

    [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.
    

    无论出于什么原因,这些方法中的哪一种更可取,还是有更好的解决方案?

    谢谢。

    5 回复  |  直到 15 年前
        1
  •  3
  •   Thilo    15 年前

    如果选择标准确实是唯一的(即最多产生一个结果),那么您将看到通过在该标准所涉及的列(或列)上有一个索引来大幅提高性能。

    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 = ?
    

    我将避免限制1,原因有两个:

    • 它是非标准SQL。我不信奉这一点,在必要的地方使用MySQL特定的东西(例如,用于分页数据),但这里不需要。
    • 如果出于某种原因,您有多行数据,这可能是应用程序中的严重错误。限制为1时,您将永远看不到问题。这就像在侏罗纪公园里计算恐龙,假设恐龙的数量可能只会下降。
        2
  •  1
  •   e4c5    15 年前

    afaik,如果您的id列上有一个索引,那么这两个查询的性能或多或少是相同的。第二个查询在程序中只需要少1行代码,但这也不会对性能产生任何影响。

        3
  •  1
  •   Darryl Hein IrishChieftain    15 年前

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

    如果我比较速度,我会说在MySQL中不计数会更快。我没有任何证据,但我想MySQL必须获取所有行,然后计算有多少行。尽管如此,在第二次思考时,它也必须在第一个选项中这样做,这样代码就会知道有多少行。但既然你有 COUNT(id) VS COUNT(*) 我会说的 might be slightly slower .

        4
  •  1
  •   Samuel    15 年前

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

    另一个选择可能是:

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

    它已经返回一个布尔值。

        5
  •  0
  •   nanda    15 年前

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

    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。