题
我知道这通常是一个坏主意,做这样的疑问:
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) FROM
group_relations这将是一个有点快,因为它不会尝试从列中检索信息。
编辑:我只是做了一些研究,发现这只是发生在一些分贝。在SQLSERVER它是使用1或*是相同的,但在Oracle它更快地使用1
显然有在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(*)
是,所以用它。