count(*)性能跟踪
学习DM8数据库的过程中,发现对表的count(*)的统计速度非常快,因此做了如下测试。
1 准备测试环境
create table t005(id int,info varchar2(100),info1 clob);
insert into t005
select rownum id,dbms_random.string(‘p’,80),dbms_random.string(‘p’,1000) name from dual connect by rownum<2000001;
SQL> select bytes/1024/1024 from dba_segments where segment_name=‘T005’;
行号 BYTES/1024/1024
1 2489 ----测试表:200w条数据,占用2489MB空间
2 执行查询性能对比
SQL> select count(*) from t005;
行号 COUNT(*)
1 2000000
已用时间: 2.927(毫秒). 执行号:500.
SQL> explain select count(*) from t005;
1 #NSET2: [209, 1, 0]
2 #PRJT2: [209, 1, 0]; exp_num(1), is_atom(FALSE)
3 #FAGR2: [209, 1, 0]; sfun_num(1),
SQL> select count(info) from t005;
行号 COUNT(INFO)
1 2000000
已用时间: 00:00:59.909. 执行号:501.
SQL> explain select count(info) from t005;
1 #NSET2: [229, 1, 48]
2 #PRJT2: [229, 1, 48]; exp_num(1), is_atom(FALSE)
3 #AAGR2: [229, 1, 48]; grp_num(0), sfun_num(1), distinct_flag[0]; slave_empty(0)
4 #CSCN2: [229, 1999999, 48]; INDEX33555460(T005)
从执行时间可以看出,count()与count(列)效率差别巨大,另外从执行计划上可以看出,count()并未使用全表扫描。
3 测试过程
•重启数据库,为了清空db buffer
/home/dmdba/dmdbms/bin/DmServiceDMSERVER restart
•查找dmserver进程id
ps –ef|grep dmserver
[root@localhost tmp]# ps -ef|grep dms
dmdba 15908 1 1 03:25 pts/1 00:00:00 /home/dmdba/dmdbms/bin/dmserver path=/home/dmdba/dmdbms/dmdb/dm.ini -noconsole
root 16020 13929 0 03:25 pts/1 00:00:00 grep --color=auto dms
•查看数据库进程打开的文件描述符
测试表存在位于MAIN.DBF,对应10。
•跟踪数据库进程id
strace -T -t -o /tmp/trace.log -fp 15908
•登录数据库执行count操作
select count(*) from t005;
查看其跟踪文件:
对10号文件,仅仅执行2次io操作,说明表段头有记录表的总数量。
select count(info) from t005;
查看其跟踪文件(仅截取一小部分):
对10号文件执行大量的io操作。
当前列info属性为可为空,因此需要count该列时,需要执行全表扫描,消耗大量IO。
修改列属性后,继续测试:
修改为非null后,效率明显提升,其执行计划与count(*)相同。
4总结
•DM8对count()做了优化,猜测在段头记录了表数量
•对表统计总量时,尽量使用count(),或count指定列的属性为非空
达梦技术社区:https://eco.dameng.com
24小时免费服务热线:400 991 6599
文章
阅读量
获赞