我知道这通常是一个坏主意,做这样的疑问:

SELECT * FROM `group_relations`

但是,当我只想伯爵,我应该去为这个查询,因为它允许表改变,但仍然得到了同样的结果。

SELECT COUNT(*) FROM `group_relations`

或者更specfic

SELECT COUNT(`group_id`) FROM `group_relations`

我有一种感觉,后者可能会更快,但是否有任何其他的事情要考虑?

<强>更新:我在这种情况下使用的是InnoDB,抱歉没有被更具体的

有帮助吗?

解决方案

如果有问题的列是NOT NULL,无论您查询的是等价的。当GROUP_ID包含空值,

select count(*)

将计算所有的行,而

select count(group_id)

其中GROUP_ID不为空将只计算行数。

此外,一些数据库系统,如MySQL采用的优化,当你问COUNT(*),这使得这样的查询有点不是具体一个速度更快。

就个人而言,如果只是算,我在做COUNT(*)是在安全方面与零点。

其他提示

如果我记得没错,在MYSQL COUNT(*)计算所有行,而COUNT(列)只计算在给定列一个非NULL值的行。

COUNT(*)计数所有的行同时COUNT(列)将在指定的列计数不NULL值仅行。

重要MySQL中要注意:

COUNT()是非常快的对*或不空列MyISAM表中,由于行计数被缓存。 InnoDB的有没有行计数缓存,所以在COUNT(*)或COUNT(列)性能没有区别,无论列是否为空或不。您可以了解更多关于在上这个帖子 MySQL的性能博客。

如果您尝试SELECT COUNT(1) FROMgroup_relations这将是一个有点快,因为它不会尝试从列中检索信息。

编辑:我只是做了一些研究,发现这只是发生在一些分贝。在SQLSERVER它是使用1或*是相同的,但在Oracle它更快地使用1

HTTP: //social.msdn.microsoft.com/forums/en-US/transactsql/thread/9367c580-087a-4fc1-bf88-91a51a4ee018/

显然有在MySQL它们之间没有区别,像SQLSERVER解析器出现改变查询来选择(1)。很抱歉,如果我误导你以某种方式。

我好奇这个自己。这是所有罚款,阅读文档和理论的答案,但我喜欢平衡那些有经验证据。

我有一个MySQL表(InnoDB的),在其具有5607997分的记录。该表是我自己的私人沙箱,所以我知道的内容是静态的,并没有其他人使用该服务器。我想,这有效地消除所有的外部影响性能。我有一个AUTO_INCREMENT主键字段(同上)的表,我知道永远不会为空,我会用我的where子句测试(其中ID为NOT NULL)。

的唯一其他可能的故障我在运行测试看的是高速缓存。第一次运行查询时总是会比使用相同的指标后续查询慢。我指的是以下作为缓存播种电话。只要给它一点混淆了我,我知道将始终为true,无论任何数据(TRUE = TRUE)的where子句跑了

这是说这里是我的结果:

查询类型

      |  w/o WHERE          | where id is not null |  where true=true

COUNT()

      |  9 min 30.13 sec ++ | 6 min 16.68 sec ++   | 2 min 21.80 sec ++
      |  6 min 13.34 sec    | 1 min 36.02 sec      | 2 min 0.11 sec 
      |  6 min 10.06 se     | 1 min 33.47 sec      | 1 min 50.54 sec

COUNT(Id)的

      |  5 min 59.87 sec    | 1 min 34.47 sec      | 2 min 3.96 sec 
      |  5 min 44.95 sec    | 1 min 13.09 sec      | 2 min 6.48 sec

COUNT(1)

      | 6 min 49.64 sec    | 2 min 0.80 sec       | 2 min 11.64 sec
      | 6 min 31.64 sec    | 1 min 41.19 sec      | 1 min 43.51 sec

++这被认为是高速缓存播种呼叫。预计为比其余部分更慢。

我想说的结果不言自明。 COUNT(同上)通常挤掉了别人。添加Where子句急剧下降,即使它是你知道的值为true子句的访问时间。甜蜜点似乎是COUNT(Id)的... WHERE ID不是NULL。

我很想看到其他人的结果,或许与小表或对地方比你正在计算领域不同领域的条款。我敢肯定有我没有考虑其他变化。

寻求替代

如您所见,当表变大,COUNT查询很慢。我认为最重要的是要考虑你正在试图解决这个问题的本质。例如,许多开发者,以确定在结果集中的总页数产生用于大的记录集分页时使用COUNT查询。

明知COUNT查询将增长缓慢,你可以考虑用另一种方式显示分页控件,简单地让你侧步慢查询。谷歌的分页是一个很好的例子。

非规范化

如果你绝对必须知道的匹配特定数量的记录数,考虑数据非规范化的经典技术。代替在查找时间计数的行数,可以考虑增加上记录插入了一个计数器,并递减上记录缺失计数器。

如果你决定这样做,可以考虑使用幂等事务性操作,以保持这些非规范化值同步。

BEGIN TRANSACTION;
INSERT INTO  `group_relations` (`group_id`) VALUES (1);
UPDATE `group_relations_count` SET `count` = `count` + 1;
COMMIT;

另外,你可以使用数据库触发器如果你的RDBMS支持他们。

根据您的架构,它可能是有意义的使用缓存层像memcached的存储,递增和递减的非标准化的值,并简单地告吹慢数查询缓存钥匙丢失时。这样可以减少总的写入争,如果你有非常不稳定的数据,但在这样的情况下,你要考虑的狗桩效果溶液

MySQL的ISAM表应该有COUNT(*)优化,跳过全表扫描。

在COUNT中的星号具有星号用于选择表的所有字段没有轴承。它的纯垃圾地说,COUNT(*)比COUNT较慢(场)

我直觉的SELECT COUNT(*)大于SELECT COUNT(场)更快。如果RDBMS检测到您指定“*”的COUNT代替领域,它并不需要评估什么增量次数。如果您在COUNT指定字段鉴于,RDBMS将始终评估,如果你的字段为空或不指望它。

但是,如果你的领域可以为空,在COUNT指定字段。

<强> COUNT(*)事实和神话:

<强>神话: “InnoDB的不处理计数(*)查询以及”:

大多数COUNT(*)查询所有的存储引擎执行相同的方式,如果你有一个WHERE子句,否则你的InnoDB将必须执行全表扫描。

<强> FACT :InnoDB的不而不where子句优化COUNT(*)查询

最好是由一个索引列计数如主键。

SELECT COUNT(`group_id`) FROM `group_relations`

这应该取决于你实际上是试图实现塞巴斯蒂安已经表示,即让你的意图明确!如果你的的只是计算的行,然后去COUNT(*),或计数一列去的COUNT(列)。

这可能是值得检查出你的数据库供应商了。回来时,我曾经使用的Informix它有对于其具有相比计数单个或复式列的1的查询计划的执行成本,这将导致更高的数字COUNT(*)的优化

  

如果您尝试SELECT COUNT(1)FROM group_relations这将是一个有点快,因为它不会尝试从列中检索信息。

COUNT(1)使用比COUNT(*)快,但事实并非如此了,因为现代DBMS都足够聪明,知道你不想知道有关列

我从MySQL有大约像这样的事情的建议是,在一般情况下,试图优化基于这样的招数查询可从长远来看,一个诅咒。有超过MySQL的历史,其中某人的依靠优化器是如何工作的高性能技术,最终被在下一版本的瓶颈例子。

编写回答你问问题的查询 - 如果你希望所有行数,使用COUNT(*)。如果您想非空列的数量,使用COUNT(COL),其中山口IS NOT NULL。指数适当的,并留下了优化优化。试图让自己的查询级优化有时可以使内置的优化效果较差。

这是说,有些事情你可以在查询做,使之更容易为优化加快步伐,但我不相信COUNT就是其中之一。

编辑:在上面的答案的统计数据是有趣的,但。我不知道是否确实在工作,在这种情况下,优化的东西。我刚才讲的一般查询级优化。

  

我知道这通常是一个坏主意,做   像这样的查询:

SELECT * FROM `group_relations`
     

但是,当我只想伯爵,应   我去为这个查询,因为它允许   表改变,但仍产生   相同的结果。

SELECT COUNT(*) FROM `group_relations`

由于您的问题暗示,SELECT *的原因是不明智的是,更改表可能需要在你的代码更改。这并不适用于COUNT(*)。这是非常罕见的需要专门的行为SELECT COUNT('group_id')给你 - 通常你想知道的记录数。这就是COUNT(*)是,所以用它。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top