关于数据库优化1——关于count(1),count(*),和count(列名)的区别,和关于表中字段顺序的问题

1.关于count(1),count(*),和count(列名)的区别

  相信大家总是在工作中,或者是学习中对于count()的到底怎么用更快。一直有很大的疑问,有的人说count(*)更快,也有的人说count(列名)更快,那到底是谁更快,我将会在本文中详细介绍一下到底是count(1),count(*)和count(列明)的区别,和更适合的使用场景。   

  往常在工作中有人会说count(1)比count(*)会快,或者相反,首先这个结论肯定是错的,实际上count(1)和count(*)并没有区别

  接下来,我们来对比一下count(*)和count(列)到底谁更快一些

  首先我们执行以下sql,来看一下执行效率(下面sql针对的是ORACLE数据库,大致逻辑为先删除t别,然后在根据dba_objects创建t表,在更新t表根据rownum)

 1 drop table t purge;
 2 create table t as select * from dba_objects;
 3 --alter table T modify object_id  null;
 4 update t set object_id =rownum ;
 5 set timing on
 6 set linesize 1000
 7 set autotrace on --开启跟踪
 8
 9 select count(*) from t;
10 /
11 select count(object_id) from t;
12 /

  然后咱们分别看一下“select count(*) from t”和“select count(object_id) from t”语句的执行计划。(执行计划是指sql的一个执行顺序和耗费的资源,耗费的资源越少越快,如果在plsql中,使用F8可以查看sql的执行计划)

  

  

  通过我们执行sql的实验来说,count(*)和count(列)消耗的资源是一样的,说面他们是一样快的,但是真的是这样么。那么咱们接着以下的实验。

  这次咱们给object_id这一列加一个索引试一下。我们执行一下索引sql

1 create index idx_object_id on t(object_id);
2 select count(*) from t;
3 /
4
5
6 select count(object_id) from t;
7 /

  然后我们在分别看一下两条sql的执行计划

  

  

  通过我们建完索引后。突然发现count(列)变快了好多,但是count(*)还是和以前一样的。这说明了count(列)可以用到索引,而count(*)不行,但是真的这样么,咱们在往下看。

  接下来我们给object_id这个字段加上不可为空条件。我们执行以下sql

1 create index idx_object_id on t(object_id);
2 select count(*) from t;
3 /
4
5
6 select count(object_id) from t;
7 /

  接下来我们在来看一下count(*)的执行计划

  

  现在count(*)和count(列)一样快了,由此我们得出了这个结论:count(列)和count(*)其实一样快,如果索引列是非空的,count(*)可用到索引,此时一样快。

  总结:但是真的结论是这样的么。其实不然。其实在数据库中count(*)和count(列)根本就是不等价的,count(*)是针对于全表的,而count(列)是针对于某一列的,如果此列值为空的话,count(列)是不会统计这一行的。所以两者根本没有可比性,性能比较首先要考虑写法等价,这两个语句根本就不等价。也就失去了去比较的意义!!!


2.关于表中字段顺序的问题

  首先我们建一张有25个字段的表并加入数据在进行count(*)和count(列)比较。由于建表语句和插入语句和上面雷同。就不贴出代码了。

然后我们分别执行count(*)和count每一列的操作来看一下到底谁更快一些,由于执行计划太多,就不一一贴图了。我整理了一个excel来给大家看一下执行的结果

  

  经过实验我们看出,count(列)越往后。我们的执行效率越慢。所以,我们得出以下结论:

     1.列的偏移量决定性能,列越靠后,访问的开销越大

      2.由于count(*)的算法与列偏移量无关,所以count(*)最快。

  总结:所以我们在开发设计中。越常用的列,要放在靠前的位置。而cout(*)和count(列)是两个不等价的用法,所以无法比较哪个性能更好,在实际的sql优化场景中要根据当时的业务场景再去考虑是使用count(*)还是count(列)(其中的区别上文有提到)。

  

  

  

  

  

  

时间: 2024-10-04 04:57:00

关于数据库优化1——关于count(1),count(*),和count(列名)的区别,和关于表中字段顺序的问题的相关文章

oracle 数据库 , 表中字段顺序修改

1.首先需要sys或者system权限操作 2.查询需要更改的表的ID select object_id from all_objects where owner = '用户名' and object_name = 'tableName';  注:表名需要大写 3.通过ID查询出该表所有字段的顺序 select obj# , col# , name from sys.col$ where obj#  = '表ID' order by col# 4.修改顺序:更改目标行 , 更改受影响的行 upd

修改MySQL数据库中表和表中字段的编码方式的方法

今天向MySQL数据库中的一张表添加含有中文的数据,可是老是出异常,检查程序并没有发现错误,无奈呀,后来重新检查这张表发现表的编码方式为latin1并且原想可以插入中文的字段的编码方式也是latin1,然后再次仔细观察控制台输出的异常,进一步确定是表和表中字段编码不当造成的,那就修改表和其中对应的字段呗,网上找了一会儿,你别说还真有,执行完sql脚本后果然可以存入中文了,尽管如此还是认为有必要总结一下,古人云:好记性不如烂笔头嘛,呵呵呵. 修改表的编码方式:ALTER TABLE `test`

一、数据库表中字段的增删改查,二、路由基础.三、有名无名分组.四、多app共存的路由分配.五、多app共存时模板冲突问题.六、创建app流程.七、路由分发.八、路由别名,九、名称空间.十、反向解析.十一、2.x新特性.十二、自定义转换器

一.数据库表中字段的增删改查 ''' 直接在modules中对字段进行增删改查 然后在tools下点击Run manage.py Task执行makemigrations和migrate 注意在执行字段的删除过程中需不需要对数据进行备份 ''' 二.路由基础 ''' # url中含有四个参数 # url(regex, view, kwargs=None, name=None) # 正则路径 视图函数地址 默认关键字参数(了解) 路由别名 # r'index' 只要请求中含有index都可以匹配成

查询数据库所有(某个)表中字段名,数据类型,说明等

--查询数据库所有 SELECT (case when a.colorder=1 then d.name else null end) 表名, a.colorder 字段序号,a.name 字段名, isnull(g.[value], ' ') AS [说明] FROM syscolumns a left join systypes b on a.xtype=b.xusertype inner join sysobjects d on a.id=d.id and d.xtype='U' and

数据库表中字段的字符串替换

很多次都有用到批量更新某字段中的一段字符串,使用此语句操作必须充分考虑到可能存在的条件,否则后果不堪设想.谨慎: Update  TableName set  ColumnName=replace(ColumnName,'OldValue','NewValue')    where     ColumnName like '%xx%'

sqlserver数据库 表中字段值有空格,如何去除空格(例如char (5) 存入数据不足5位时sqlserver会自动补空格)

普通的空格 前后的空格,使用LTrim和RTrim即可,例如:LTrim(RTrim(Name)) 中间的空格,使用replace函数替换,例如:Replace(Name,' ','') 如果是普通的空格,很容易替换,但有时候会遇到一些特殊的空格,就比较麻烦,看起来跟普通的空格一模一样,但就是无法替换掉.这就需要特殊的方法去找出空格,然后用replace替换. 找出这样的空格,需要用到ascii函数,通过ascii函数,找出空格的ascii值,然后用replace函数+char函数来替换. 例如

java怎样读取数据库表中字段的数据类型?

用DriverManager.getConnection()得到connect, 用connect.getMetaData()得到 DatabaseMetaData, 用 DatabaseMetaData.getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)得到相应字段的ResultSet. 用ResultSet.getMetaData() 得到Res

MYSQL数据库表中字段追加字符串内容

$sql="update parts set p_notes=concat(p_notes,'{$p_notes}') where p_id={$p_id}"; parts为表名 p_notes为字段名 {p_notes}为要追加的内容

Postgres查看数据库中的表及表中字段和类型

\dt \d \q 如上图, \dt命令比在pgAdminIII中查看表方便多了 \d命令查看表的字段类型