学习show_space存储过程

251 篇文章 6 订阅
237 篇文章 8 订阅

今天学习和介绍一个有用的工具,来自TOM大神的show_space,其实这就是一个存储过程,用他可以统计一些段的用度,非常方便,网上流传着不同的版本。


首先我们看下原版的脚本,https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:5350053031470

create or replace 
procedure show_space 
( p_segname in varchar2, 
p_owner in varchar2 default user, 
p_type in varchar2 default 'TABLE', 
p_partition in varchar2 default NULL ) 
authid current_user 
as 
l_free_blks number; 

l_total_blocks number; 
l_total_bytes number; 
l_unused_blocks number; 
l_unused_bytes number; 
l_LastUsedExtFileId number; 
l_LastUsedExtBlockId number; 
l_LAST_USED_BLOCK number; 
procedure p( p_label in varchar2, p_num in number ) 
is 
begin 
dbms_output.put_line( rpad(p_label,40,'.') || 
p_num ); 
end; 
begin 
for x in ( select tablespace_name 
from dba_tablespaces 
where tablespace_name = ( select tablespace_name 
from dba_segments 
where segment_type = p_type 
and segment_name = p_segname 
and SEGMENT_SPACE_MANAGEMENT <> 'AUTO' ) 

loop 
dbms_space.free_blocks 
( segment_owner => p_owner, 
segment_name => p_segname, 
segment_type => p_type, 
partition_name => p_partition, 
freelist_group_id => 0, 
free_blks => l_free_blks ); 
end loop; 

dbms_space.unused_space 
( segment_owner => p_owner, 
segment_name => p_segname, 
segment_type => p_type, 
partition_name => p_partition, 
total_blocks => l_total_blocks, 
total_bytes => l_total_bytes, 
unused_blocks => l_unused_blocks, 
unused_bytes => l_unused_bytes, 
LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId, 
LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId, 
LAST_USED_BLOCK => l_LAST_USED_BLOCK ); 

p( 'Free Blocks', l_free_blks ); 
p( 'Total Blocks', l_total_blocks ); 
p( 'Total Bytes', l_total_bytes ); 
p( 'Total MBytes', trunc(l_total_bytes/1024/1024) ); 
p( 'Unused Blocks', l_unused_blocks ); 
p( 'Unused Bytes', l_unused_bytes ); 
p( 'Last Used Ext FileId', l_LastUsedExtFileId ); 
p( 'Last Used Ext BlockId', l_LastUsedExtBlockId ); 
p( 'Last Used Block', l_LAST_USED_BLOCK ); 
end; 

/

从原版来看,根据dba_tablespaces、dba_segments检索出表空间的名称,使用dbms_space包的free_blocks和unused_space计算相应空间,格式化输出,其中有一点需要注意,就是只会统计SEGMENT_SPACE_MANAGEMENT <> 'AUTO'的表空间,即MANUAL手工管理的表空间。


这个脚本最开始是2002年针对9i版本发布的帖子,


直到2014年,还有人跟帖,足以见其影响力,


我们用实验来体会一下,创建测试表,



执行存储过程,


删除数据,



空间不会释放,



truncate数据,



此时表空间则被初始化,



我们看几个改良的版本,

(1) 惜分飞版本,

http://www.xifenfei.com/2011/09/tom%E7%9A%84show_space%E8%BF%87%E7%A8%8B%E4%BD%BF%E7%94%A8.html

create or replace procedure show_space
( p_segname_1 in varchar2,
p_owner_1 in varchar2 default user,
p_type_1 in varchar2 default 'TABLE',
p_space in varchar2 default 'AUTO',
p_analyzed in varchar2 default 'Y'
)
as
p_segname varchar2(100);
p_type varchar2(10);
p_owner varchar2(30);
 
l_unformatted_blocks number;
l_unformatted_bytes number;
l_fs1_blocks number;
l_fs1_bytes number;
l_fs2_blocks number;
l_fs2_bytes number;
l_fs3_blocks number;
l_fs3_bytes number;
l_fs4_blocks number;
l_fs4_bytes number;
l_full_blocks number;
l_full_bytes number;
 
l_free_blks number;
l_total_blocks number;
l_total_bytes number;
l_unused_blocks number;
l_unused_bytes number;
l_LastUsedExtFileId number;
l_LastUsedExtBlockId number;
l_LAST_USED_BLOCK number;
 
procedure p( p_label in varchar2, p_num in number )
is
begin
dbms_output.put_line( rpad(p_label,40,'.') ||
p_num );
end;
begin
p_segname := upper(p_segname_1); -- rainy changed
p_owner := upper(p_owner_1);
p_type := p_type_1;
 
if (p_type_1 = 'i' or p_type_1 = 'I') then --rainy changed
p_type := 'INDEX';
end if;
 
if (p_type_1 = 't' or p_type_1 = 'T') then --rainy changed
p_type := 'TABLE';
end if;
 
if (p_type_1 = 'c' or p_type_1 = 'C') then --rainy changed
p_type := 'CLUSTER';
end if;

dbms_space.unused_space
( segment_owner => p_owner,
segment_name => p_segname,
segment_type => p_type,
total_blocks => l_total_blocks,
total_bytes => l_total_bytes,
unused_blocks => l_unused_blocks,
unused_bytes => l_unused_bytes,
LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,
LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
LAST_USED_BLOCK => l_LAST_USED_BLOCK );
 
if p_space = 'MANUAL' or (p_space <> 'auto' and p_space <> 'AUTO') then
dbms_space.free_blocks
( segment_owner => p_owner,
segment_name => p_segname,
segment_type => p_type,
freelist_group_id => 0,
free_blks => l_free_blks );
 
p( 'Free Blocks', l_free_blks );
end if;
 
p( 'Total Blocks', l_total_blocks );
p( 'Total Bytes', l_total_bytes );
p( 'Unused Blocks', l_unused_blocks );
p( 'Unused Bytes', l_unused_bytes );
p( 'Last Used Ext FileId', l_LastUsedExtFileId );
p( 'Last Used Ext BlockId', l_LastUsedExtBlockId );
p( 'Last Used Block', l_LAST_USED_BLOCK );

/*IF the segment is analyzed */
if p_analyzed = 'Y' then
dbms_space.space_usage(segment_owner => p_owner ,
segment_name => p_segname ,
segment_type => p_type ,
unformatted_blocks => l_unformatted_blocks ,
unformatted_bytes => l_unformatted_bytes,
fs1_blocks => l_fs1_blocks,
fs1_bytes => l_fs1_bytes ,
fs2_blocks => l_fs2_blocks,
fs2_bytes => l_fs2_bytes,
fs3_blocks => l_fs3_blocks ,
fs3_bytes => l_fs3_bytes,
fs4_blocks => l_fs4_blocks,
fs4_bytes => l_fs4_bytes,
full_blocks => l_full_blocks,
full_bytes => l_full_bytes);
dbms_output.put_line(rpad(' ',50,'*'));
dbms_output.put_line('The segment is analyzed');
p( '0% -- 25% free space blocks', l_fs1_blocks);
p( '0% -- 25% free space bytes', l_fs1_bytes);
p( '25% -- 50% free space blocks', l_fs2_blocks);
p( '25% -- 50% free space bytes', l_fs2_bytes);
p( '50% -- 75% free space blocks', l_fs3_blocks);
p( '50% -- 75% free space bytes', l_fs3_bytes);
p( '75% -- 100% free space blocks', l_fs4_blocks);
p( '75% -- 100% free space bytes', l_fs4_bytes);
p( 'Unused Blocks', l_unformatted_blocks );
p( 'Unused Bytes', l_unformatted_bytes );
p( 'Total Blocks', l_full_blocks);
p( 'Total bytes', l_full_bytes);
 
end if;
 
end;
/


其特点就是,可以接受AUTO类型管理的表空间,可以接受I、T、C作为索引、堆表和聚簇表的简写,如果段已被分析,则回显中会包含空闲空间块百分比,更直观展示表的使用情况,


(2) Dave版本

http://blog.csdn.net/tianlesoftware/article/details/8151129

CREATE OR REPLACE PROCEDURE show_space (
   p_segname_1     IN VARCHAR2,
   p_type_1        IN VARCHAR2 DEFAULT 'TABLE',
p_space         IN VARCHAR2 DEFAULT'MANUAL',
   p_analyzed      IN VARCHAR2 DEFAULT 'N',
p_partition_1   IN VARCHAR2 DEFAULTNULL,
   p_owner_1       IN VARCHAR2 DEFAULT USER)
   AUTHID CURRENT_USER
AS
   p_segname              VARCHAR2 (100);
   p_type                 VARCHAR2 (30);
   p_owner                VARCHAR2 (30);
   p_partition            VARCHAR2 (50);
 
   l_unformatted_blocks   NUMBER;
   l_unformatted_bytes    NUMBER;
   l_fs1_blocks           NUMBER;
   l_fs1_bytes            NUMBER;
   l_fs2_blocks           NUMBER;
   l_fs2_bytes            NUMBER;
   l_fs3_blocks           NUMBER;
   l_fs3_bytes            NUMBER;
   l_fs4_blocks           NUMBER;
   l_fs4_bytes            NUMBER;
   l_full_blocks          NUMBER;
   l_full_bytes           NUMBER;
 
   l_free_blks            NUMBER;
   l_total_blocks         NUMBER;
   l_total_bytes          NUMBER;
   l_unused_blocks        NUMBER;
   l_unused_bytes         NUMBER;
   l_LastUsedExtFileId    NUMBER;
   l_LastUsedExtBlockId   NUMBER;
   l_LAST_USED_BLOCK      NUMBER;
 
   PROCEDURE p (p_label IN VARCHAR2,p_num IN NUMBER)
   IS
   BEGIN
      DBMS_OUTPUT.put_line (RPAD(p_label, 40, '.') || p_num);
   END;
BEGIN
   p_segname := UPPER (p_segname_1);
   p_owner := UPPER (p_owner_1);
   p_type := p_type_1;
   p_partition := UPPER(p_partition_1);
 
   IF (p_type_1 = 'i' OR p_type_1 ='I')
   THEN
      p_type := 'INDEX';
   END IF;
 
   IF (p_type_1 = 't' OR p_type_1 ='T')
   THEN
      p_type := 'TABLE';
   END IF;
 
   IF (p_type_1 = 'tp' OR p_type_1 ='TP')
   THEN
      p_type := 'TABLE PARTITION';
   END IF;
 
   IF (p_type_1 = 'ip' OR p_type_1 = 'IP')
   THEN
      p_type := 'INDEX PARTITION';
   END IF;
 
   IF (p_type_1 = 'c' OR p_type_1 ='C')
   THEN
      p_type := 'CLUSTER';
   END IF;
 
   DBMS_SPACE.UNUSED_SPACE (
      segment_owner               => p_owner,
      segment_name                => p_segname,
      segment_type                => p_type,
      partition_name              => p_partition,
      total_blocks                => l_total_blocks,
      total_bytes                 => l_total_bytes,
      unused_blocks               => l_unused_blocks,
      unused_bytes                => l_unused_bytes,
      LAST_USED_EXTENT_FILE_ID    => l_LastUsedExtFileId,
      LAST_USED_EXTENT_BLOCK_ID   => l_LastUsedExtBlockId,
      LAST_USED_BLOCK             => l_LAST_USED_BLOCK);
 
   IF p_space = 'MANUAL' OR (p_space<> 'auto' AND p_space <> 'AUTO')
   THEN
      DBMS_SPACE.FREE_BLOCKS (segment_owner       => p_owner,
                             segment_name        =>p_segname,
                              segment_type        => p_type,
                             partition_name      =>p_partition,
                             freelist_group_id   => 0,
                             free_blks           =>l_free_blks);
 
      p ('Free Blocks', l_free_blks);
   END IF;
 
   p ('Total Blocks',l_total_blocks);
   p ('Total Bytes', l_total_bytes);
   p ('Unused Blocks',l_unused_blocks);
   p ('Unused Bytes',l_unused_bytes);
   p ('Last Used Ext FileId',l_LastUsedExtFileId);
   p ('Last Used Ext BlockId', l_LastUsedExtBlockId);
   p ('Last Used Block',l_LAST_USED_BLOCK);
 
   /*IF the segment is analyzed */
   IF p_analyzed = 'Y'
   THEN
      DBMS_SPACE.SPACE_USAGE(segment_owner        => p_owner,
                             segment_name         => p_segname,
                             segment_type         => p_type,
                             partition_name       =>p_partition,
                              unformatted_blocks   => l_unformatted_blocks,
                             unformatted_bytes    =>l_unformatted_bytes,
                             fs1_blocks           =>l_fs1_blocks,
                             fs1_bytes            =>l_fs1_bytes,
                             fs2_blocks           =>l_fs2_blocks,
                              fs2_bytes            => l_fs2_bytes,
                             fs3_blocks           =>l_fs3_blocks,
                             fs3_bytes            =>l_fs3_bytes,
                             fs4_blocks           =>l_fs4_blocks,
                              fs4_bytes            => l_fs4_bytes,
                             full_blocks          =>l_full_blocks,
                             full_bytes           =>l_full_bytes);
      DBMS_OUTPUT.put_line (RPAD ('', 50, '*'));
      DBMS_OUTPUT.put_line ('Thesegment is analyzed');
      p ('0% -- 25% free spaceblocks', l_fs1_blocks);
      p ('0% -- 25% free spacebytes', l_fs1_bytes);
      p ('25% -- 50% free spaceblocks', l_fs2_blocks);
      p ('25% -- 50% free spacebytes', l_fs2_bytes);
      p ('50% -- 75% free spaceblocks', l_fs3_blocks);
      p ('50% -- 75% free spacebytes', l_fs3_bytes);
      p ('75% -- 100% free spaceblocks', l_fs4_blocks);
      p ('75% -- 100% free spacebytes', l_fs4_bytes);
      p ('Unused Blocks', l_unformatted_blocks);
      p ('Unused Bytes',l_unformatted_bytes);
      p ('Total Blocks',l_full_blocks);
      p ('Total bytes',l_full_bytes);
   END IF;
END;
/

这个版本是(1)的基础上支持了分区,以及接受IP和TP作为索引分区和表分区的简写。


另外,以下文章中有类似show_space的改良版,但逻辑原理基本一致,可以根据自己的需求,选择适合自己的一个版本,

http://blog.csdn.net/indexman/article/details/47207987

http://blog.csdn.net/huang_xw/article/details/7015349


总结:

1. show_space这个存储过程可以方便我们统计表/索引/聚簇表等段的使用情况,不用写一些SQL来实现此目标。

2. show_space有不同版本,有的支持分区,有的支持各种不同段的简写,有的支持细粒度的统计,根据自己的需求,选择一款适合自己的版本,了解其中的实现原理,将工具的设计思想,据为己用,触类旁通,甚至可以进行一些改造。



如果您觉得此篇文章对您有帮助,欢迎关注微信公众号:bisal的个人杂货铺,您的支持是对我最大的鼓励!共同学习,共同进步:)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
lr = 2e-3 num_episodes = 500 hidden_dim = 128 gamma = 0.98 epsilon = 0.01 target_update = 10 buffer_size = 10000 minimal_size = 500 batch_size = 64 device = torch.device("cuda") if torch.cuda.is_available() else torch.device( "cpu") env_name = 'CartPole-v1' env = gym.make(env_name) random.seed(0) np.random.seed(0) #env.seed(0) torch.manual_seed(0) replay_buffer = ReplayBuffer(buffer_size) state_dim = env.observation_space.shape[0] action_dim = env.action_space.n agent = DQN(state_dim, hidden_dim, action_dim, lr, gamma, epsilon, target_update, device) return_list = [] episode_return = 0 state = env.reset()[0] done = False while not done: action = agent.take_action(state) next_state, reward, done, _, _ = env.step(action) replay_buffer.add(state, action, reward, next_state, done) state = next_state episode_return += reward # 当buffer数据的数量超过一定值后,才进行Q网络训练 if replay_buffer.size() > minimal_size: b_s, b_a, b_r, b_ns, b_d = replay_buffer.sample(batch_size) transition_dict = { 'states': b_s, 'actions': b_a, 'next_states': b_ns, 'rewards': b_r, 'dones': b_d } agent.update(transition_dict) if agent.count >=200: #运行200步后强行停止 agent.count = 0 break return_list.append(episode_return) episodes_list = list(range(len(return_list))) plt.plot(episodes_list, return_list) plt.xlabel('Episodes') plt.ylabel('Returns') plt.title('DQN on {}'.format(env_name)) plt.show()对上述代码的每一段进行注释,并将其在段落中的作用注释出来
最新发布
06-12
``` lr = 2e-3 # 学习率 num_episodes = 500 # 训练的总Episode数 hidden_dim = 128 # 隐藏层维度 gamma = 0.98 # 折扣因子 epsilon = 0.01 # ε贪心策略中的ε值 target_update = 10 # 目标网络更新频率 buffer_size = 10000 # 经验回放缓冲区的最大容量 minimal_size = 500 # 经验回放缓冲区的最小容量,达到此容量后才开始训练 batch_size = 64 # 每次训练时的样本数量 device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") # 选择CPU或GPU作为运行设备 env_name = 'CartPole-v1' # 使用的环境名称 env = gym.make(env_name) # 创建CartPole-v1环境 random.seed(0) # 随机数生成器的种子 np.random.seed(0) # 随机数生成器的种子 torch.manual_seed(0) # 随机数生成器的种子 replay_buffer = ReplayBuffer(buffer_size) # 创建经验回放缓冲区 state_dim = env.observation_space.shape[0] # 状态空间维度 action_dim = env.action_space.n # 动作空间维度(离散动作) agent = DQN(state_dim, hidden_dim, action_dim, lr, gamma, epsilon, target_update, device) # 创建DQN智能体 return_list = [] # 用于存储每个Episode的回报 episode_return = 0 # 每个Episode的初始回报为0 state = env.reset()[0] # 环境的初始状态 done = False # 初始状态下没有结束 ``` 以上代码是对程序中所需的参数进行设置和初始化,包括学习率、训练的总Episode数、隐藏层维度、折扣因子、ε贪心策略中的ε值、目标网络更新频率、经验回放缓冲区的最大容量、经验回放缓冲区的最小容量、每次训练时的样本数量、运行设备、使用的环境名称等等。同时,创建了经验回放缓冲区、DQN智能体和用于存储每个Episode的回报的列表,以及初始化了环境状态和结束标志。 ``` while not done: action = agent.take_action(state) # 智能体根据当前状态选择动作 next_state, reward, done, _, _ = env.step(action) # 环境执行动作,观测下一个状态、奖励和结束标志 replay_buffer.add(state, action, reward, next_state, done) # 将当前状态、动作、奖励、下一个状态和结束标志添加到经验回放缓冲区中 state = next_state # 更新状态 episode_return += reward # 累加当前Episode的回报 ``` 以上代码是智能体与环境的交互过程,智能体根据当前状态选择动作,环境执行动作并返回下一个状态、奖励和结束标志,将当前状态、动作、奖励、下一个状态和结束标志添加到经验回放缓冲区中,更新状态,并累加当前Episode的回报。 ``` if replay_buffer.size() > minimal_size: # 当经验回放缓冲区的数据量达到最小容量时,开始训练 b_s, b_a, b_r, b_ns, b_d = replay_buffer.sample(batch_size) # 从经验回放缓冲区中采样样本 transition_dict = { 'states': b_s, 'actions': b_a, 'next_states': b_ns, 'rewards': b_r, 'dones': b_d } agent.update(transition_dict) # 智能体根据样本更新Q网络 if agent.count >=200: # 运行200步后强行停止 agent.count = 0 break ``` 以上代码是经验回放和Q网络更新过程,当经验回放缓冲区的数据量达到最小容量时,从经验回放缓冲区中采样样本,智能体根据样本更新Q网络。同时,当运行步数超过200步时,强制停止训练。 ``` return_list.append(episode_return) # 将当前Episode的回报添加到回报列表中 ``` 以上代码是将当前Episode的回报添加到回报列表中。 ``` episodes_list = list(range(len(return_list))) # 横坐标为Episode序号 plt.plot(episodes_list, return_list) # 绘制Episode回报随序号的变化曲线 plt.xlabel('Episodes') plt.ylabel('Returns') plt.title('DQN on {}'.format(env_name)) plt.show() ``` 以上代码是绘制Episode回报随序号的变化曲线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值