`
hypgr
  • 浏览: 273469 次
社区版块
存档分类
最新评论

oracle count计数的优化

阅读更多

在9i,我们知道count(*)的时候,如果表上有pk,那count(*) 一定会走pk的。count(column) ,如果column指定not null,那count(column)  可以走上索引(通过试验证明,必须还要加上index提示才能走上索引)。但如果列上有空值,不管如何加提示,都走不上列上的索引(组合索引的非引导列除外)

       count是否应该走索引,主要取决于count是否应该把空值算进来。所以, count(column) ,不管字段是否有null,都可以走索引。进而我们可以推论,如果表上存在一not null的字段,而且这个字段上有索引,表上即使没有pk,count(*)也可以通过扫描整个索引完成计数。在11g里面,oracle改进了策略。测试如下:

在9i里面,无论如何写提示,都没办法走上COL_IND索引的。因为col1字段允许为null(虽然实际数据没有null值,分析统计信息也是没用的)
此时count(*),全表扫描:

如我们推论的那样,即使没有PK,存在一个not null的字段,且字段上有索引。count(*)会使用表完成计数。
但如果一个无pk的表上出现多个not null且有索引的字段,那count(*)走哪个索引呢?我们很自然的想到了成本。哪个成本小,走哪个。测试一下:

1 consistent gets

>create table test (col1 varchar2(32),col2 varchar2(32));
 

Table created
>insert into test
2 select id,member_id
3 from b where rownum<=10;
>select * from test;

COL1 COL2
——————————– ——————————–
477234 shenzhenxiechang
291004 shenzhoutouzi
345045 hgyingzi
212170 ntdongyi
493284 ntfashion
200282 rebecca123
1199257 szjinshuipos
629740 nttg
1512060 rich228
772466 nxyk

>create index col_ind on test (col1);
>create index co2_ind on test (col2);
Index created.
Index created.
>select count(col1) from test;

COUNT(COL1)
———–
10

1 row selected.

Execution Plan
———————————————————-
Plan hash value: 4154769577

—————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————-
| 0 | SELECT STATEMENT | | 1 | 7 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
| 2 | INDEX FULL SCAN| COL_IND | 10 | 70 | 1 (0)| 00:00:01 |
—————————————————————————-

>select count(*) from test;
 

COUNT(*)
———-
10

1 row selected.

Execution Plan
———————————————————-
Plan hash value: 1950795681

——————————————————————-
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
——————————————————————-
| 0 | SELECT STATEMENT | | 1 | 18 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TEST | 10 | 18 (0)| 00:00:01 |
——————————————————————-

把其中一个字段改为not null:
>alter table test modify(col2 not null);

Table altered.
>desc test
Name Null? Type
———————————————————————————– ——– ——————————————————–
COL1 VARCHAR2(32)
COL2 NOT NULL VARCHAR2(32)

>select count(*) from test;

COUNT(*)
———-
10

1 row selected.

Execution Plan
———————————————————-
Plan hash value: 73288374

——————————————————————–
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
——————————————————————–
| 0 | SELECT STATEMENT | | 1 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FULL SCAN| CO2_IND | 10 | 1 (0)| 00:00:01 |
——————————————————————–

>update test set col2=col2||lpad(col2,3500,’a');
 

10 rows updated.
>analyze table test compute statistics for all indexes;

Table analyzed.
update字段前的索引统计信息:
name NUM_ROWS distinct LEAF_BLOCKS cf level alfbpkey
—————————— ———- ———- ———– ———- ———- ———-
CO2_IND 10 10 1 1 0 1
COL_IND 10 10 1 1 0 1
update之后的:
name NUM_ROWS distinct LEAF_BLOCKS cf level alfbpkey
—————————— ———- ———- ———– ———- ———- ———-
CO2_IND 10 10 5 1 1 1
COL_IND 10 10 1 1 0 1

>select count(*) from test;

COUNT(*)
———-
10

1 row selected.

Execution Plan
———————————————————-
Plan hash value: 4154769577

——————————————————————–
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
——————————————————————–
| 0 | SELECT STATEMENT | | 1 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FULL SCAN| COL_IND | 10 | 1 (0)| 00:00:01 |
——————————————————————–

CBO还是根据访问索引的成本选择了成本小的索引进行访问。如果通过index提示,走CO2_IND.
6 consistent gets这个时候,pk对于count(*)来说完全无意义了。完全通过成本决定走哪个索引


注:由于手里没10g的测试环境,不知道这个改进是否在10g就已经有了。

>alter table test add constraint test_pk primary key (col2);
 

Table altered.

>>select count(*) from test;

COUNT(*)
———-
10

1 row selected.

Execution Plan
———————————————————-
Plan hash value: 4154769577

——————————————————————–
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
——————————————————————–
| 0 | SELECT STATEMENT | | 1 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FULL SCAN| COL_IND | 10 | 1 (0)| 00:00:01 |

分享到:
评论

相关推荐

    ORACLE9i_优化设计与系统调整

    第一部分 ORACLE系统优化基本知识 23 第1章 ORACLE结构回顾 23 §1.1 Oracle数据库结构 23 §1.1.1 Oracle数据字典 23 §1.1.2 表空间与数据文件 24 §1.1.3 Oracle实例(Instance) 24 §1.2 Oracle文件 26 §1.2.1...

    merge_row_count:一个简单的实用程序,允许对由 Oracle 中的合并操作插入更新删除的行进行计数

    一个简单的实用程序 PL/SQL 包,允许对 Oracle 中的合并操作插入/更新/删除的行进行计数。 包的需要 Oracle不提供获取行数的功能。 插入 更新 已删除 使用 MERGE 操作完成所有操作时。 这个简单的实用程序是为了...

    Oracle分析函数

    COUNT :对一组内发生的事情进行累积计数 ------------------------------------------------------------------------------------------------- RANK :根据ORDER BY子句中表达式的值,从查询返回的每一行,计算...

    Oracle查询表里的重复数据方法

     按照id分组并计数,某个id号那一组的数量超过1条则认为重复。 如何查询重复的数据 select 字段1,字段2,count(*) from 表名 group by 字段1,字段2 having count(*) &gt; 1 PS:将上面的&gt;号改为=号就可以查询出没有...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 第一章 Oracle入门 一、 数据库概述 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今五十年前。简单来说是本身可视...

    解析如何查看Oracle数据库中某张表的字段个数

    Oracle中查询某个表的总字段数,要用SQL语句,或者在PL/SQL里面 代码如下:select count(column_name) from user_tab_columns where table_name=’T_B_AUDITOR’能够查出来指定的那张表的字段数。下面是通过大致查看...

    精通SQL 结构化查询语言详解

    8.2.2 计数函数-COUNT()  8.2.3 最大/最小值函数-MAX()/MIN()  8.2.4 均值函数-AVG()  8.2.5 聚合分析的重值处理  8.2.6 聚合函数的组合使用  8.3 组合查询  8.3.1 GROUP BY子句创建分组  8.3.2 ...

    精通SQL--结构化查询语言详解

    8.2.2 计数函数—count() 140 8.2.3 最大/最小值函数—max()/min() 143 8.2.4 均值函数—avg() 145 8.2.5 聚合分析的重值处理 147 8.2.6 聚合函数的组合使用 148 8.3 组合查询 148 8.3.1 group by子句创建分组...

    PL/SQL学习笔记

    1.count属性计数 ,可以得到集合的元素数量 2.delete方法 3.exists 判断这个元素是否存在,exists(x) 4.extend方法 不带参数加一个元素 extend(x)加x个元素 extend(x,y) 5.first属性,返回第一个元素...

    2009达内SQL学习笔记

    如果指定列名,则DISTINCT只能用于COUNT(列名),DISTINCT不能用于COUNT(*)。 如:Select Distinct name From s_dept; Select Distinct dept_id,title From s_emp; 文本处理: TRIM()/LTRIM()/RTIRM():去空格。...

    PHP基础教程 是一个比较有价值的PHP新手教程!

    echo count($a); // 打印出3,因为该是数组有3个元素 // 用一个语句定义一个数组并赋值 $myphonebook = array ( "sbabu" =&gt; "5348", "keith" =&gt; "4829", "carole" =&gt; "4533" ); // 噢,忘了教长吧,让我们添加一个...

    精髓Oralcle讲课笔记

    -- 首先,以超级管理员的身份登录oracle sqlplus sys/bjsxt as sysdba --然后,解除对scott用户的锁 alter user scott account unlock; --那么这个用户名就能使用了。 --(默认全局数据库名orcl) 1、...

    mysql基础只是总结

    mssql 2000 Access DB2 oracle 【mysql安装】 1、官方下载mysql win32 msi 2、点击安装 3、配置 4、查看是否安装成功 通过cmd 输入netstat -a搜索3306端口是否处于listening状态 【mysql服务的启动与停止】 1...

    SQL语句大全 珍藏版2019-02-28

    函数 AVG (平均) COUNT (计数) MAX (最大值) MIN (最小值) SUM (总合) SELECT "函数名"("栏位名") FROM "表格名" (10) COUNT .................................... .............. ..................................

    经典SQL语句大全

    set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定 '+ @strWhere 2、收缩数据库 --重建索引 DBCC REINDEX DBCC INDEXDEFRAG --收缩数据和日志 DBCC SHRINKDB DBCC SHRINKFILE 3、...

    数据库操作语句大全(sql)

    set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定 '+ @strWhere 2、收缩数据库 --重建索引 DBCC REINDEX DBCC INDEXDEFRAG --收缩数据和日志 DBCC SHRINKDB DBCC SHRINKFILE 3、...

    sql经典语句一部分

    set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定 '+ @strWhere 2、收缩数据库 --重建索引 DBCC REINDEX DBCC INDEXDEFRAG --收缩数据和日志 DBCC SHRINKDB DBCC SHRINKFILE 3、...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例143 使用线程池优化多线程编程 186 实例144 Object类中线程相关的方法 187 实例145 哲学家就餐问题 189 实例146 使用信号量实现线程同步 190 实例147 使用原子变量实现线程同步 191 实例148 使用事件分配线程...

Global site tag (gtag.js) - Google Analytics