高水位线对于全表扫描的影响

本文探讨了全表扫描的概念及其在Oracle数据库中的工作原理,特别是在ASMM环境下。通过实验展示了空闲数据块如何显著增加全表扫描的成本,并介绍了通过收缩表来优化HWM的方法。

      简单来说,全表扫描就是扫描表中的所有数据块,包括空数据块。在ASMM的环境下,全表扫描通常是扫描到低高水位线(Low HWM),然后通过位图扫描低高水位线到高水位线之间格式化的数据块。在ASMM环境下,当空间不足的时候,oracle就会分配新的区间给表,然后HWM随即就会提高,但是数据库并没有马上格式化这些新分配的数据块,而是等到需要使用这些数据块的时候才格式化这些数据块。为此,low HWM到HWM之间很有可能存在非格式化的数据块。如下图:


      为此,全表扫描的效率主要受到空闲数据块以及结果的返回率的影响。对于存在大量空闲数据块的全表扫描成本将会很高,因为其同时读取了大量的空数据块。要解决这个问题,可以通过重建表、收缩表等方法来降低HWM。下面的实验是验证空数据块对于全表扫描性能的影响,以及采用收缩表的方式降低HWM.

----通过PCTFREE制造大量数据块
SQL> create table t1(
  2  id int,
  3  time date)
  4  pctfree 80
  5  pctused 10;

表已创建。

SQL> begin
  2  for i in 1..100000 loop
  3  insert into t1
  4  select i,sysdate+i from dual;
  5  end loop;
  6  end;
  7  /

PL/SQL 过程已成功完成。

SQL> delete from t1 where id>10;

已删除99990行。

SQL> create index ind on t1(id);

索引已创建。

SQL> analyze table t1 compute statistics;---分析表,获取统计数据;

表已分析。

SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name ='T1';

TABLE_NAME                       NUM_ROWS     BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1                                     10       1133           18

SQL> select index_name,clustering_factor from user_indexes where index_name ='IND';

INDEX_NAME                     CLUSTERING_FACTOR
------------------------------ -----------------
IND                                            1
----由上面两个SELECT语句可以知道,10行数据聚集在一个数据块里,其他的都没有数据,也就是说水位线很高。

SQL> set autotrace traceonly explain;

-----因此,下面的全表扫描耗费了巨大的成本;
SQL> select count(*) from t1;

执行计划
----------------------------------------------------------
Plan hash value: 3724264953

-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   309   (0)| 00:00:04 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| T1   |    10 |   309   (0)| 00:00:04 |
-------------------------------------------------------------------

----而,若使用索引则扫描成本则非常低;
SQL> select count(*) from t1 where id>=1;

执行计划
----------------------------------------------------------
Plan hash value: 1947457635

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     2 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |      |     1 |     2 |            |          |
|*  2 |   INDEX RANGE SCAN| IND  |    10 |    20 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("ID">=1)

----从上面的两个性能差异,说明了全表扫描会很大程度上受到空闲数据块的影响;
SQL>

### 3.1 Oracle 中水位线HWM)的概念 在 Oracle 数据库中,**水位线**(High Water Mark, HWM)是一个用于标识段空间中已使用和未使用块的边界标记。每当一张表被创建时,Oracle 会为其分配一个段空间,并随着数据的插入,该段空间中的块逐步被填充,HWM 随之上升[^2]。 水位线的作用在于指示数据库哪些块曾经被使用过。即使数据被删除(如执行 DELETE 操作),HWM 也不会自动下降,这意味着全表扫描仍然需要访问所有曾被使用的块,导致性能下降[^3]。 ### 3.2 重置水位线的意义 **重置水位线**是指将 HWM 向下移动至当前实际存储数据所占用的空间位置。这一操作可以显著提升查询性能,特别是在大量删除操作之后。由于 Oracle 在进行全表扫描时会读取所有位于 HWM 以下的数据块,即使这些块已经被清空,因此保留较HWM 会导致不必要的 I/O 开销和逻辑读操作[^3]。 通过某些特定操作(如 TRUNCATE 或 MOVE 表),可以有效地降低 HWM,从而减少后续查询对空块的扫描,提执行效率。TRUNCATE 命令不仅清空数据,还会重置 HWM,使得表的存储结构更加紧凑[^1]。 ```sql -- 示例:TRUNCATE 操作会重置水位线 TRUNCATE TABLE test_tab; ``` ### 3.3 如何理解重置水位线的行为 重置水位线可以理解为对表存储结构的一次“整理”。当大量数据被删除后,虽然表中不再有记录,但 Oracle 依然认为那些块是“可能使用过的”,因此不会释放它们供其他对象使用。这种行为类似于文件系统中删除文件后磁盘空间并未立即回收的情况。 只有在执行某些 DDL 操作(如 TRUNCATE、ALTER TABLE MOVE)或重建索引等动作时,才会触发 HWM 的重新定位,使数据库知道哪些块真正可用。这种方式有助于优化物理存储利用率并提升查询性能[^2]。 ### 3.4 相关操作与影响 - **DELETE 操作**:仅删除数据内容,不改变 HWM 位置,因此全表扫描仍需访问所有历史使用的块。 - **TRUNCATE 操作**:属于 DDL 操作,不仅清空数据,还重置 HWM,释放存储空间(取决于是否启用 `REUSE STORAGE` 选项)。 - **ALTER TABLE MOVE**:将表数据迁移到新的段空间,同时压缩碎片并重置 HWM。 ```sql -- 示例:使用 ALTER TABLE MOVE 重置 HWM ALTER TABLE test_tab MOVE; ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值