当我需要去做优化时,有一个固定的优化思路:SQL优化->索引优化->分区优化->优化器hints优化
SQL 语句优化
- A. 字符级的比较: 当前被执行的语句和共享池中的语句必须完全相同.
- B. 两个语句所指的对象必须完全相同
- C. 两个 SQL 语句中必须使用相同的名字的绑定变量(bind variables)
索引优化
多个平等的索引
在 SQL 语句包含多个表时,且使用分布在表上的多个索引时,ORACLE 会同时使用多个索引 并运行时对他们的记录进行合并,检索出仅对全部索引有效的记录.
唯一性索引的等级是最高的,但是,只有当索引在 WHERE 子句中与常量比较的时候才有效, 如果与其他表的索引相比较,那么这个子句在优化器中等级是最低的.
如果不同表的两个同等级的索引被引用,那么将有 FROM 子句中表的顺序决定,既 FROM 最 后面的表的索引优先级最高
如果同表的两个相同等级的索引被引用,那么 WHERE 子句中最先被引用的索引将有最高优先级.
等式比较和范围比较
当WHERE子句中存在索引列的比较时,ORACLE是不会优先对进行比较的索引进行访问的. 所以尽量避免对索引列进行范围比较.进行范围比较的索引访问级别很低.即使是唯一性索引也 是一样.
索引的自动选择规则
如果一个表中有很多索引,但是只有一个是唯一性索引,那么 ORACLE 只会对唯一性索引进 行访问而完全忽略其他非唯一性索引.......
- 避免对索引使用 NOT
- 避免在索引列上使用 IS NULL OR IS NOT NULL
- 使用索引的第一个列,
- 避免改变索引列的类型
分区优化
改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度(个人评价只针对条件中带分区字段的查询性能)。
增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用(鸡蛋不放一个篮子里的概念)。
维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可(各数据文件之间相互独立,互不影响)。
均衡I/O:可以把不同的分区映射到不同磁盘以平衡I/O,改善整个系统性能(这个针对整体的查询性能,但是分区必须放在不同的表空间,每个表空间尽量分布在不同的磁盘上,这样可以充分利用各个磁盘的I/O来提高效率)
① 分区键的选择: 选择合适的分区键对于表分区的效果至关重要。分区键应该是经常被查询和过滤的列,以便在查询时能够快速定位到目标分区。此外,分区键的选择还应考虑到数据的均匀分布和未来的扩展性。例如,在销售数据表中,可以选择按照日期、地区或产品类别等字段进行分区。
② 子分区: 在某些情况下,单一分区可能仍然过大,导致查询性能下降。这时可以考虑使用子分区来进一步细分数据。子分区可以按照更具体的条件对分区进行进一步划分,例如按照地区、销售人员或产品类型进行子分区。通过细粒度的子分区,可以更精确地定位到需要查询的数据,提高查询效率。
③ 分区策略: 根据数据的特性和查询需求,选择适当的分区策略也是优化表分区的关键。常见的分区策略包括范围分区、列表分区、哈希分区和复合分区等。根据具体情况选择合适的分区策略,可以更好地满足业务需求,提高查询和维护的效率。
④ 分区维护: 定期对分区进行维护操作是保证表分区性能的重要环节。维护操作包括分区合并、分区拆分、分区移动和分区压缩等。通过合理的维护操作,可以减少分区数目,优化存储空间的利用率,提高查询性能和维护效率。
⑤ 分区索引: 为分区表创建适当的索引也是优化表分区的关键。根据查询的模式和频率,选择合适的索引类型和列,以提高查询的效率。对于分区表,通常会为分区键和常用查询条件创建索引,以实现快速的分区导航和查询性能的提升。
⑥ 分区交换: 分区交换是一种高效的数据加载和数据归档技术,可用于快速插入大量数据或归档历史数据。通过分区交换,可以在两个分区之间直接交换数据,而无需实际移动数据的物理位置,从而极大地减少了数据加载和归档的时间和资源消耗。
优化器hints的优化
不要过分依赖Hint
当遇到SQL执行计划不好的情况,应优先考虑统计信息等问题,而不是直接加Hint了事。如果统计信息无误,应该考虑物理结构是否合理,即没有合适的索引。只有在最后仍然不能SQL按优化的执行计划执行时,才考虑Hint。
毕竟使用Hint,需要应用系统修改代码,Hint只能解决一条SQL的问题,并且由于数据分布的变化或其他原因(如索引更名)等,会导致SQL再次出现性能问题。
Hint的弊端
-
Hint是比较"暴力"的一种解决方式,不是很优雅。需要开发人员手工修改代码。
-
Hint不会去适应新的变化。比如数据结构、数据规模发生了重大变化,但使用Hint的语句是感知变化并产生更优的执行计划。
-
Hint随着数据库版本的变化,可能会有一些差异、甚至废弃的情况。此时,语句本身是无感知的,必须人工测试并修正。
Hint功能
Hint提供的功能非常丰富,可以很灵活地调整语句的执行过程。通过Hint,我们可以调整:
-
优化器类型
-
优化器优化目标
-
数据读取方式(访问路径)
-
查询转换类型
-
表间关联的顺序
-
表间关联的类型
-
并行特性
-
其他特性
Hint用法
关键字说明
-
DELETE、INSERT、SELECT和UPDATE是标识一个语句块开始的关键字,包含提示的注释只能出现在这些关键字的后面,否则提示无效。
-
"+"号表示该注释是一个提示,该加号必须立即跟在"/*"的后面,中间不能有空格。
-
hint是下面介绍的具体提示之一,如果包含多个提示,则每个提示之间需要用一个或多个空格隔开。
-
text是其它说明hint的注释性文本
提示中的错误
提示中的语法错误不会报错,如果解析器不能解析它,就会把它看做一个普通注释处理。这也是容易造成困惑的一点,使用的Hint到底是否起效?可以采用一些手段,检查提示的有效性。需要注意的是,那些语法正确但引用对象错误的提示是不会被报告的。
-
explain plan + dbms_xplan
使用dbms_xplan输出中的note选项。
-
10132事件
在10g中,这个事件产生的输出文档的末尾有一部分内容专门讲提示。通过它可以检查两个方面:一是每个用到的提示都会被列出来。如果漏掉了哪个,就说明这个提示没有被识别;二是检查是否有一些信息指明了出现提示错误(如果出错,err值将大于0)。
提示中的对象
SELECT /*+ INDEX(table_name index_name) */ ...
-
table_name是必须要写的,且如果在查询中使用了表的别名,在hint也要用表的别名来代替表名。
-
index_name可以不必写,Oracle会根据统计值选一个索引。
-
如果索引名或表名写错了,那这个hint就会被忽略。
-
如果指定对象是视图,需要按此方法指定。/*+hint view.table ...*/,其中table是view中的表。
-
一个很常见的错误时,在使用提示的时候最易犯的错误是与表的别名有关。正确的规则是,当在提示中使用表时,只要表有别名就应该使用别名而不是表名。
Hint分类
和优化器相关的
当对优化器为某个语句所制定的基本执行计划不满意时,最好的办法就是通过提示来转换优化器的模式,并观察其转换后的结果,看是否已经达到期望程度。如果只通过转换优化器的模式就可以获得非常好的执行计划,则就没有必要额外使用更为复杂的提示了。
-
OPT_PARAM
这个提示的作用就是使我们在某条语句中指定某个系统参数值。
-
ALL_ROWS
为实现查询语句整体最优化而引导优化器制定最少成本的执行计划。这个提示会使优化器选择一条可最快检索所有查询行的路径,而代价就是在检索一行数据时,速度很慢。
-
FIRST_ROWS
为获得最佳响应时间而引导优化器制定最少成本的执行计划。这个提示会使优化器选择可最快检索出查询的第一行(或指定行)数据的路径,而代价就是检索很多行时速度就会很慢。利用FIRST_ROWS来优化的行数,默认值为1,这个值介于10到1000之间,这个使用FIRST_ROWS(n)的新方法是完全基于代价的方法。它对n很敏感,如果n值很小,CBO就会生成包含嵌套循环以及索引查找的计划;如果n很大,CBO会生成由哈希连接和全表扫描组成的计划(类似ALL_ROWS)。
-
CHOOSE
依据SQL中所使用到的表的统计信息存在与否,来决定使用RBO还是CBO。在CHOOSE模式下,如果能够参考表的统计信息,则将按照ALL_ROWS方式执行。除非在查询中的所有表都没有经过分析,否则choose提示会对整个查询使用基于代价的优化。如果在多表连接中有一个表经过分析过,那么就会对整个查询进行基于代价的优化。
-
RULE
使用基于规则的优化器来实现最优化执行,即引导优化器根据优先顺序规则来决定查询条件中所使用到的索引或运算符的执行顺序来制定执行计划。这个提示强制oracle优先使用预定义的一组规则,而不是对数据进行统计;同时该提示还会使这个语句避免使用其他提示,除了DRIVING_SITE和ORDERED(不管是否进行基于规则的优化,这两个提示都可使用)。
和访问路径相关的
-
FULL
告诉优化器通过全表扫描方式访问数据。这个提示只对所指定的表进行全表扫描,而不是查询中的所有表。FULL提示可以改善性能。这主要是因为它改变了查询中的驱动表,而不是因为全表扫描。在使用其他某些提示时,也必须使用FULL提示。只有访问整个表时,才可利用CACHE提示将表进行缓存。并行组中的某些提示也必须使用全表扫描。
-
CLUSTER
引导优化器通过扫描聚簇索引来从索引表中读取数据。
-
HASH
引导优化器按照哈希扫描的方式从表中读取数据。
-
INDEX
告诉优化器对指定表通过索引的方式访问数据。当访问数据会导致结果集不完整时,优化器将忽略这个Hint。
-
NO_INDEX
告诉优化器对指定表不允许使用索引。这个提示会禁止优化器使用指定索引。可以在删除不必要的索引之前在许多查询中禁止索引。如果使用了NO_INDEX,但是没有指定任何索引,则会执行全表扫描。如果对某个索引同时使用了NO_INDEX和会之产生冲突的提示(如INDEX),这时两个提示都会被忽略掉。
-
INDEX_ASC
利用索引从表中读取数据时,引导优化器对提示中所指定索引的索引列值按照升序使用范围扫描。
-
INDEX_COMBINE
告诉优化器强制选择位图索引。这个提示会使优化器合并表上的多个位图索引,而不是选择其中最好的索引(这是INDEX提示的用途)。还可以使用index_combine指定单个索引(对于指定位图索引,该提示优先于INDEX提示)。对于B树索引,可以使用AND_EQUAL提示而不是这个提示。
-
INDEX_JOIN
索引关联,当谓词中引用的列上都有索引的时候,可以通过索引关联的方式来访问数据。这个提示可以将同一个表的各个不同索引进行合并,这样就只需要访问这些索引就可以了,节省了回表查询的时间。但只能在基于代价的优化器中使用该提示。这个提示不仅允许只访问表上的索引,这样可以扫描更少的代码块,并且它比使用索引并通过rowid扫描整个表快5倍。
-
INDEX_DESC
利用索引从表中读取数据时,引导优化器对提示中所指定索引的索引列值按照降序使用范围扫描。
-
INDEX_FFS
告诉优化器以INDEX FFS(index fast full scan)的方式访问数据。INDEX_FFS提示会执行一次索引的快速全局扫描。这个提示只访问索引,而不是对应的表。只有查询需要检索的信息都在索引上时,才使用这个提示。特别在表有很多列时,使用该提示可以极大地改善性能。
-
INDEX_SS
强制使用index skip scan的方式访问索引。当在一个联合索引中,某些谓词条件并不在联合索引的第一列时(或者谓词并不在联合索引的第一列时),可以通过index skip scan来访问索引获得数据。当联合索引第一列的唯一值很少时,使用这种方式比全表扫描的方式效率要高。
和查询转换相关的
-
USE_CONCAT
将含有多个OR或者IN运算符所连接起来的查询语句分解为多个单一查询语句,并为每个单一查询语句选择最优化查询路径,然后再将这些最优化查询路径结合在一起,以实现整体查询语句的最优化目的。只有在驱动查询条件中包含OR的时候,才可以使用该提示。
-
NO_EXPAND
引导优化器不要为使用OR运算符号(或IN运算符)的条件制定相互结合的执行计划。正好和USE_CONCAT相反。
-
REWRITE
当表连接的对象是数据量比较大的表或者需要获得使用统计函数处理过的结果时,为了提高执行速度可预先创建物化视图。当用户要求查询某个查询语句时,优化器会在从表中和从物化视图中读取数据的两种方法中选择一个更有效的方法来读取数据。该执行方法称之为查询重写。使用REWRITE提示引导优化器按照该方式执行。
-
MERGE
为了能以最优方式从视图或者嵌套视图中读取数据,通过变换查询语句来直接读取视图使用的基表数据,该过程被称之为视图合并。不同的情况其具体使用类型也有所不同。该提示主要在视图未发生合并时被使用。尤其是对比较复杂的视图或者嵌套视图(比如使用了GROUP BY或DISTINC的视图)使用该提示,有时会取得非常好的效果。
-
UNNEST
提示优化器将子查询转换为连接的方式。也就是引导优化器合并子查询和主查询并且将其向连接类型转换。
-
NO_UNNEST
引导优化器让子查询能够独立地执行完毕之后再跟外围的查询做FILTER。
-
PUSH_PRED
使用该提示可以将视图或嵌套视图以外的查询条件推入到视图之内。
-
NO_PUSH_PRED
使用该提示确保视图或嵌套视图以外的查询条件不被推入到视图内部。
-
PUSH_SUBQ
使用该提示引导优化器为不能合并的子查询制定执行计划。不能合并的子查询被优先执行之后,该子查询的执行结果将扮演缩减主查询数据查询范围的提供者角色。通常在无法执行子查询合并的情况下,子查询扮演的都是检验者角色,所以子查询一般被放在最后执行。在无法被合并的子查询拥有较少的结果行,或者该子查询可以缩减主查询查询范围的情况下,可以使用该提示引导优化器最大程度地将该子查询放在前面执行,以提高执行速度。但如果子查询执行的是远程表或者排序合并连接的一部分连接结果,则该提示将不起任何作用。
-
NO_PUSH_SUBQ
使用该提示将引导优化器将不能实现合并的子查询放在最后执行。在子查询无法缩减主查询的查询范围,或者执行子查询开销较大的情况下,将这样的子查询放在最后执行可以在某种程度上提高整体的执行效率。也就是说,尽可能地使用其他查询条件最大程度地缩减查询范围之后,再执行子查询。
和表连接顺序相关的
这些提示可以调整表连接的顺序。调整表连接的顺序并不是只能使用这些提示,在嵌套循环连接方式中也可以让提示来引导优化器使用由驱动查询条件所创建的索引。然而,该方法只有在使用的索引和表连接顺序同时被调整的情况下才比较有效。一般而言,这些提示主要在执行多表连接和表之间的连接顺序比较混乱的情况下才使用,也在排序合并连接或哈希连接方式下,为引导优化器优先执行数据量比较少得表时使用。
-
LEADING
在一个多表关联的查询中,这个Hint指定由哪个表作为驱动表,即告诉优化器首先要访问那个表上的数据。引导优化器使用LEADING指定的表作为表连接顺序中的第一个表。该提示既与FROM中所描述的表的顺序无关,也与作为调整表连接顺序的ORDERED提示不同,并且在使用该提示时并不需要调整FROM中所描述的表的顺序。当该提示与ORDERED提示同时使用时,该提示被忽略。
这个提示类似ORDERED提示,它允许指定驱动查询的表,然后由优化器来判断下一个要访问的表。如果使用这个提示指定多张表,那么就可以忽略这个提示。
-
ORDERED
引导优化器按照FROM中所描述的表的顺序执行连接。如果和LEADING提示被一起使用,则LEADING提示将被忽略。由于ORDERED只能调整表连接的顺序并不能改变表连接的方式,所以为了改变表的连接方式,经常将USE_NL、USE_MERGE提示与ORDERED提示放在一起使用。
和表连接操作相关的
-
USE_NL
使用该提示引导优化器按照嵌套循环连接方式执行表连接。它只是指出表连接的方式,对于表连接顺序不会有任何影响。
-
USE_MERGE
引导优化器按照排序合并连接方式执行连接。在有必要的情况下,推荐将该提示与ORDERED提示一起使用。提示通常用于获得查询的最佳吞吐量。假设将两个表连接在一起,从每个表返回的行集将被排序,然后再被合并(也就是合并排序),从而组成最终的结果集。由于每个行先被排序之后才进行合并,所以在给定查询中检索所有行时,速度将会最快。如果需要以最快速度返回第一行,就应该使用USE_NL提示。
-
USE_HASH
该提示引导优化器按照哈希连接方式执行连接。在执行哈希连接时,如果由于某一边的表比较小,从而可以在内存中实现哈希连接,那么就能够获得非常好的执行速度。由于在大部分情况下优化器会通过对统计信息的分析来决定Build Input和Prove Input,所以建议不要使用ORDERED提示随意改变表的连接顺序。但是当优化器没能做出正确判断时,或者像从嵌套视图中所获得的结果集合那样不具备统计信息时,可以使用该提示。
和并行相关的
-
PARALLEL
指定SQL执行的并行度,这个值将会覆盖表自身设定的并行度。如果这个值为default,CBO使用系统参数。从表中读取大量数据和执行DML操作时使用该提示来指定SQL的并行操作。一般情况下需要在该提示中指定将要使用的并行线程个数。如果在该提示中没有指定并行度的个数,则优化器将使用PARALLEL_THREADS_PER_CPU参数所指定的值进行自动计算。如果在定义表时指定了PARALLEL,那么在能够使用并行操作的情况下,即使没有使用该提示,优化器也会按照指定的并行级别选择并行操作。但是如果想在DELETE、INSERT、UPDATE、MERGE等DML操作中使用并行操作,则必须要在会话中设置ALTER SESSION ENABLE PARALLEL DML。在某个会话中所设置的并行级别也可以被引用在内部的GROUP BY或者排序操作中。在并行操作中如果出现了某个限制要素,则该提示将被忽略。
-
NO PARALLEL/NO_PARALLEL
在SQL语句禁止使用并行。在有些版本中用NO_PARALLEL提示来代替NOPARALLEL提示。
-
PQ_DISTRIBUTE
为了提高并行连接的执行速度,使用该提示来定义使用何种方法在主从进程之间(例如生产者进程和消费者进程)分配各连接表的数据行。
-
PARALLEL_INDEX
为了按照并行操作的方式对分区索引进行索引范围扫描而使用该提示,并且可以指定进程的个数。
其他相关的
-
APPEND
让数据库以直接加载的方式(direct load)将数据加载入库。这个提示不会检查当前是否有插入所需要的块空间,相反它会直接将数据添加到新块中。这样会浪费空间,但可以提高插入的性能。需要注意的是,数据将被存储在HWM之上的位置。
-
APPEND_VALUES
在11.2中,Oracle新增了APPEND_VALUES提示,使得INSERT INTO VALUES语句也可以使用直接路径插入。
-
CACHE
在全表扫描之后,数据块将留在LRU列表的最活跃端。如果设置表的CACHE属性,它的作用和HINT一样。这个提示会将全表扫描全部缓存到内存中。如果表很大,会占用大量内存。因此适用于用户经常访问的较小的表。
-
NOCACHE
引导优化器将通过全表扫描方式获取的数据块缓存在LRU列表的最后位置,这样可以让数据库实例缓存中的这些数据块被优先清除。这是优化器在Buffer Cache中管理数据块的默认方法(仅针对全表扫描)。
-
QB_NAME
使用该提示为查询语句块命名,在其他查询语句块可以直接使用该查询语句块的名称。
-
DRIVING_SITE
这个提示在分布式数据库操作中有用。指定表是处理连接所在的位置。可以限制通过网络处理的信息量。此外,还可以建立远程表的本地视图来限制从远程站点检索的行。本地视图应该有where子句,从而视图可以在将行发送回本地数据库之前限制从远程数据库返回的行。
-
DYNAMIC_SAMPLING
提示SQL执行时动态采样的级别。这个级别为0~10,它将覆盖系统默认的动态采样级别。等级越高,所获得统计信息的准确率越高。该提示的功能就是为了确保将动态采样原理应用在单个SQL中。
-
AND_EQUAL
这个提示会使优化器合并表上的多个索引,而不是选择其中最好的索引(这是INDEX提示的用途)。这个提示与前面的INDEX_JOIN提示有区别,以此指定的合并索引随后需访问表,而INDEX_JOIN提示则只需访问索引。如果发现需经常用到这个提示,可能需要删除这些单个索引而改用一个组合索引。需要查询条件里面包括所有索引列,然后取得每个索引中得到的rowid列表。然后对这些对象做merge join,过滤出相同的rowid后再去表中获取数据或者直接从索引中获得数据。在10g中,and_equal已经废弃了,只能通过hint才能生效。
-
CARDINALITY
向优化器提供对某个查询语句的整体或部分的预测基数值,并通过参考该基数值来为查询语句制定执行计划。如果在该提示中没有指定表的名称,则该基数值将被视为从该查询语句所获得的最终结果行数。
CSDNhttps://mp.csdn.net/mp_blog/creation/editor/138309193
高水位调节
什么是 高水位标记 High Water Mark
块Block
块:是粒度最小的存储单位,现在标准的块大小是8K,ORACLE每一次I/O操作也是按块来操作的,也就是说当ORACLE从数据文件读数据时,是读取多少个块,而不是多少行. 每一个Block里可以包含多个row.
区Extent
由一系列相邻的块而组成,这也是ORACLE空间分配的基本单位.区extent是比数据块大一级的存储结构,表示的是一连串连续的数据块集合。
段Segment
段: 是由一系列的区extent所组成. 数据段是与数据库对象相对应,一般一个数据库对象对应一个数据段。多个extent是对应一个数据段,每个数据段实际上就是数据库一个对象的代表。一般来说, 当创建一个对象时(表,索引),就会分配一个段给这个对象.
表空间tableSpace
表空间: 包含段,区及块.表空间的数据物理上储存在其所在的数据文件中.一个数据库至少要有一个表空间.
Oracle 数据库 逻辑结构包括:数据库块(block),扩展(extent 区),段(segment),表空间(tablespace)。高水位线就存在于段(segment)中,它用于标识段中已使用过的数据块与未使用过的数据块二者间交界,扫描表数据的时候,高水位线以下的所有数据块都必须被扫描。
高水位线存在于段,且高水位线的位置记录在段头,也就是段的第一个数据块中。因此,我们可以转存储段头信息来看高水位信息。
HWM通常增长的幅度为一次5个数据块,原则上HWM只会增大,不会缩小,即使将表中的数据全部删除,HWM还是为原值,由于这个特点,使HWM很象一个水库的历史最高水位,这也就是HWM的原始含义,当然不能说一个水库没水了,就说该水库的历史最高水位为0。但是如果我们在表上使用了truncate命令,则该表的HWM会被重新置为0。
高水位标记的影响
- 全表扫描要读出直到HWM标记的所有的属于该表的数据块(used space),即使该表中没有任何数据;
- 即使HWM下有空闲的数据块,如果在插入数据时使用了append参数,则在插入数据时使用HWM以上的数据块,HWM会自动增大。
Oracle表段中的高水位线
每个Oracle数据块在ASSM段中都属于下面的一种状态:
- 高水位线以上
这些块未被格式化且从来没有被使用过。
- 高水位线以下(3类)
--已经分配,但是未格式化和未使用;
--格式化,且含有数据;
--格式化,不含有数据,因为数据被删除了。
1. 在创建表的时候,HWM位于segment左边的起始处,因为没有数据插入,segment中全部的block未被格式化和从未被使用
2. 假设一个事务将行数据插入到segmnet中,数据库必须分配一组数据块去保存行信息,被分配的数据块全在HWM之下,数据库格式化一个位图块来保存元数据,但是没有指定是哪一个数据块。
在HWM以下的数据块是被分配的,在HWM以上的数据块从未被分配和格式化。当insert时,数据可以写到有可用空间的任何块中。low HWM以下的部分,所有的块都被格式化,因为它们要么含有数据,要么以前包含数据。
3. 当insert时,数据库选择在HWM和low HWM之间的任意一个块进行写入,或者是HWM以下的一个有空闲空间的块进行写入。
4. low HWM对于全表扫描是非常重要的。因为HWM以下的数据块只有在要使用时才格式化,有一些块还未格式化。基于这个原因,数据库会去bitmap块查询low HWM的位置,然后会去读low HWM以下的全部数据块,因为数据库已经知道这些块全部被格式化了,对于在low HWM和HWM之间的数据块,数据库会挑选那些已经格式化了的数据块进行读操作。
5. 假设一个新的事务进行插入操作,但是bitmap指示目前在HWM以下已经没有足够的空间了,数据库会向右移动该segment的HWM,分配一组新的未格式化的数据块。
降低HWM
SHRINK
shrink技术是一种段收缩技术,可将表与索引高水位以下的碎片进行有效压缩,并将高水位进行回退。
step1. 启用行移动
SQL > ALTER TABLE table_name ENABLE ROW MOVEMENT;
step2. 压缩数据及下调HWM
SQL > ALTER TABLE table_name SHRINK SPACE CASCADE; --压缩表及相关数据段并下调HWM
或
SQL > ALTER TABLE table_name SHRINK SPACE COMPACT; --只压缩数据不下调HWMSQL > ALTER TABLE table_name SHRINK SPACE; --下调HWM
即该技术可以一次性压缩数据及下调HWM,也可以分两个阶段进行,第一阶段:在业务高峰,只压缩数据不下调HWM,第二阶段:在业务空闲时,下调HWM。
MOVE Tablespace
SQL > ALTER TABLE table_name MOVE TABLESPACE tablepsace_name;
--MOVE后不跟参数也行,不跟参数还是原来的表空间;
--MOVE后需要重建索引;
--如果以后还要向表里插入数据,没必要MOVE。MOVE释放出来的空间,只能这个表使用,其它的表或者segment无法使用。
CTAS技术
即重建表技术。
SQL > CREATE TABLE new_table_name AS SELECT * FROM old_table_name; --将表的数据写入到一张新的表里SQL > DROP TABLE old_table_name; --删除旧表SQL > RENAME table new_table_name TO old_table_name --将新表名更改为旧表名
DEALLOCATE技术
利用DEALLOCATE技术可以回收HWM以上从未使用过的数据块。语法如下
SQL > ALTER TABLE table_name DEALLOCATE UNUSED [KEEP integer]; SQL > ALTER INDEX index_name DEALLOCATE UNUSED [KEEP integer];
MOVE与SHRINK的区别
MOVE | SHRINK(仅对ASSM有效) | |
本质 | move实际上是block级别的数据块拷贝,对表进行move后,该表所在blockid会发生改变数据的rowid自然也会发生改变,但是数据在table中的存储顺序并没有发生改变 | shrink是对行数据进行移动。对表进行shrink后,部分行数据的rowid发生了变化,而table所位于的block区域的位置却没有发生变化。 |
重建索引 | 需要重建 | 可以通过cascade关键字重建 |
锁 | TM(exclusive) | TM(SX) |
空间要求 | 需要有原表大的空闲空间 | 不需要额外的空间 |
效果 | 压缩后会回收空间 | 压缩后会回收空间 |