10、管理数据库存储(行迁移及行连接)

管理数据库存储

1block=8192bytes

案例1:行迁移

1、表中数据如何存储

create table test as select * from hr.employees;

create index idx_test on test(employee_id);

只看执行计划,不执行结果。

set autotrace traceonly statistics;

select * from test where employee_id>0;

强制走索引

select /*+index(test,idx_test_id) */ * from test where employee_id>0;

SQL> select /*+index(test,idx_test_id) */ * from test where employee_id>0;

107 rows selected.

Statistics

----------------------------------------------------------

7  recursive calls

0  db block gets

19  consistent gets

0  physical reads

0  redo size

9096  bytes sent via SQL*Net to client

601  bytes received via SQL*Net from client

9  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

107  rows processed

解读:19  consistent gets 需要19个block才能存107行数据

set autotrace off;

alter table test modify FIRST_NAME  varchar2(1000);

alter table test modify LAST_NAME  varchar2(1000);

alter table test modify EMAIL  varchar2(1000);

alter table test modify PHONE_NUMBER  varchar2(1000);

update test set LAST_NAME=lpad(LAST_NAME,1000,‘*‘),FIRST_NAME=lpad(FIRST_NAME,1000,‘*‘),EMAIL=lpad(EMAIL,1000,‘*‘),PHONE_NUMBER=lpad(PHONE_NUMBER,1000,‘*‘);

SQL> set autotrace traceonly statistics;

SQL> select /*+index(test,idx_test_id) */ * from test where employee_id>0;

107 rows selected.

Statistics

----------------------------------------------------------

9  recursive calls

0  db block gets

288  consistent gets

0  physical reads

0  redo size

438255  bytes sent via SQL*Net to client

601  bytes received via SQL*Net from client

9  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

107  rows processed

SQL> set autotrace off;

SQL> @/u01/app/oracle/product/11.2.0/db_1/rdbms/admin/utlchain.sql

Table created.

其中表结构为:

create table CHAINED_ROWS (

owner_name         varchar2(30),

table_name         varchar2(30),

cluster_name       varchar2(30),

partition_name     varchar2(30),

subpartition_name  varchar2(30),

head_rowid         rowid,

analyze_timestamp  date

);

把test表行行迁移信息放到这张表 CHAINED_ROWS 中

analyze table test list chained rows into CHAINED_ROWS;

select table_name,count(*) from CHAINED_ROWS group by table_name;

SQL> select table_name,count(*) from CHAINED_ROWS group by table_name;

TABLE_NAME COUNT(*)

------------------------------ ----------

TEST      105

这里表示 TEST 表有107行数据,其中105行数据搬家了。发生了行迁移。

如何消除行迁移???

1、把发生行迁移的行放到一个临时表中

create table test_temp as select * from test where rowid in (select head_rowid from CHAINED_ROWS);

SQL> select count(*) from test_temp;

COUNT(*)

----------

105

2、删除行迁移的行

select rowid,employee_id from test;

delete from test where rowid in (select head_rowid from CHAINED_ROWS)

SQL> delete from test where rowid in (select head_rowid from CHAINED_ROWS);

105 rows deleted.

SQL> select count(*) from test;

COUNT(*)

----------

2

3、插入

insert into test  select * from test_temp;

SQL> select count(*) from test;

  COUNT(*)
----------
       107

commit;

truncate table CHAINED_ROWS;

查看有没有行迁移

analyze table test list chained rows into CHAINED_ROWS;

select table_name,count(*) from CHAINED_ROWS group by table_name;

set autotrace traceonly statistics;

select /*+index(test,idx_test_id) */ * from test where employee_id>0;

结果为:

SQL> select /*+index(test,idx_test_id) */ * from test where employee_id>0;

107 rows selected.

Statistics

----------------------------------------------------------

0  recursive calls

0  db block gets

116  consistent gets

0  physical reads

0  redo size

437625  bytes sent via SQL*Net to client

601  bytes received via SQL*Net from client

9  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

107  rows processed

结论:对比一下行迁移之前读了288 block  现在只要读了116个 block;

案例2:行连接  说明一行的数据超过8192bytes

truncate table CHAINED_ROWS;

drop table test_temp purge;

drop table test purge;

set autotrace off;

create table test as select * from hr.employees;

create index idx_test_id on test(employee_id);

set autotrace traceonly statistics;

select /*+ index(test,idx_test_id)*/ * from test;

set autotrace off;

alter table test modify last_name varchar2(2000);

alter table test modify first_name varchar2(2000);

alter table test modify email varchar2(2000);

alter table test modify phone_number varchar2(2000);

update test set LAST_NAME=lpad(‘1‘,2000,‘*‘),FIRST_NAME=lpad(‘1‘,2000,‘*‘),EMAIL=lpad(‘1‘,2000,‘*‘),PHONE_NUMBER=lpad(‘1‘,2000,‘*‘);

commit;

SQL> desc test;

Name   Null?    Type

----------------------------------------- -------- ----------------------------

EMPLOYEE_ID    NUMBER(6)

FIRST_NAME    VARCHAR2(2000)

LAST_NAME   NOT NULL VARCHAR2(2000)

EMAIL   NOT NULL VARCHAR2(2000)

PHONE_NUMBER    VARCHAR2(2000)

HIRE_DATE   NOT NULL DATE

JOB_ID   NOT NULL VARCHAR2(10)

SALARY    NUMBER(8,2)

COMMISSION_PCT    NUMBER(2,2)

MANAGER_ID    NUMBER(6)

DEPARTMENT_ID    NUMBER(4)

set autotrace traceonly statistics;

select /*+ index(test,idx_test_id)*/ * from test;

107 rows selected.

Statistics

----------------------------------------------------------

28  recursive calls

0  db block gets

399  consistent gets

0  physical reads

0  redo size

869120  bytes sent via SQL*Net to client

601  bytes received via SQL*Net from client

9  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

107  rows processed

set autotrace off;

analyze table test list chained rows into CHAINED_ROWS;

select table_name,count(*) from CHAINED_ROWS group by table_name;

SQL> select table_name,count(*) from CHAINED_ROWS group by table_name;

TABLE_NAME COUNT(*)

------------------------------ ----------

TEST      214

那如何消除行连接呢?

SQL> show parameter 16k

NAME     TYPE VALUE

------------------------------------ ----------- ------------------------------

db_16k_cache_size     big integer 0

alter system set db_16k_cache_size=20m;

select name from v$datafile;

SQL> select name from v$datafile;

NAME

--------------------------------------------------------------------------------

+DATA/orcl/datafile/system.256.943301251

+DATA/orcl/datafile/sysaux.257.943301251

+DATA/orcl/datafile/undotbs1.258.943301251

+DATA/orcl/datafile/users.259.943301251

+DATA/orcl/datafile/example.265.943301433

创建16K的表空间(之前默认1个block是8192bytes字节)

create tablespace  tbs_16k blocksize 16K datafile ‘+DATA/orcl/datafile/tbs.dbf‘ size 10m;

alter table test move tablespace tbs_16k;

truncate table CHAINED_ROWS;

analyze table test list chained rows into CHAINED_ROWS;

select table_name,count(*) from CHAINED_ROWS group by table_name;

因为刚才对表空间进行了move,因此test的索引生效了,需要重建索引。

alter index idx_test_id rebuild;

set autotrace traceonly statistics;

select /*+ index(test,idx_test_id)*/ * from test;

SQL> select /*+ index(test,idx_test_id)*/ * from test;

107 rows selected.

Statistics

----------------------------------------------------------

36  recursive calls

0  db block gets

177  consistent gets

0  physical reads

0  redo size

867337  bytes sent via SQL*Net to client

601  bytes received via SQL*Net from client

9  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

107  rows processed

结论:读107行数据, 对比之前读了399个block,现在只读了177个block

时间: 2024-08-05 10:03:19

10、管理数据库存储(行迁移及行连接)的相关文章

Oracle行迁移和行链接

行迁移和行链接都会导致Oracle性能下降,这篇文章将介绍什么是行迁移和行链接,它们带来的问题,如何来判断它们,并提供了解决它们的办法. 什么是行迁移和行链接 行迁移 Oracle的数据块会保留部分空间供以后更新使用,通常的数据块结构如下: PCTFREE定义一个块保留的空间百分比,默认是10,表示当数据块的可用空间低于10%后,就不可以被insert了,只能被update(具体看下面的PCTFREE介绍). 当一条记录被更新时,数据库引擎首先会尝试在它保存的数据块中寻找足够的空闲空间,如果没有

centos下mysql的安装及数据库存储目录迁移

wget http://repo.mysql.com/mysql57-community-release-el7-8.noarch.rpm rpm –ivh mysql57-community-release-el7-8.noarch.rpm yum install mysql-server 进入/etc 编辑my.cnf 在最后一行加上 skip-grant-tables 跳过MySQL密码验证 service mysqld restart 重启数据库 mysql -u root 直接进入数据

ORACLE 行迁移和行链接

1. 行迁移 当发出update导致记录行长增加,block的剩余空间不足以存放这条记录,就会产生行迁移,发生行迁移时rowid不会改变,原来的block 中会用一个指针存放这条记录在新的block中的地址,发生行迁移会对性能产生影响,因为读这条记录会读两个BLOCK. 行迁移:导致应用需要访问更多的数据块,性能下降. 预防行迁移:1. 将数据块的PCTFREE调大:2. 针对表空间扩大数据块大小 消除行迁移的办法: 创建行迁移表,$ORACLE_HOME/rdbms/admin目录下的utlc

[转]Oracle DB 管理数据库存储结构

? 描述块中表行数据的存储 ? 创建和管理表空间 ? 获取表空间信息 表数据的存储方式 创建表时,还会创建一个用于保存其数据的段.表空间包含一个段集合. 从逻辑上来说,表包含许多行列值.行最终以行片段的形式存储在数据库块中.之所以称其为行片段,是因为在某些情况下可能不会在一个位置存储完整的行.当插入的行太大而无法装入单个块时(链接行),或当更新导致现有行超出当前块的可用空闲空间时(迁移行),就会发生这种情况.当表中的列多于255 列时,也会使用行片段.在这种情况下,这些行片段可能位于同一个块(块

模拟Oracle行迁移和行链接

行链接消除方法创建大的block块------------------ 参考tom kyte的例子----------------------------------------------创建4k blocksize的表空间SQL> alter system set db_4k_cache_size=1m scope=both; System altered.SQL> create tablespace tbs1 datafile '/u01/app/oracle/oradata/test/

mysql数据库存储过程数据迁移案例与比较

cursor 与 insert ...select 对比: cursor:安全,不会造成死锁,可以在服务运行阶段跑,比较稳定. insert...select :速度快,但是可能造成死锁,相比cursor能够成倍提升,在服务停止的情况下迁移,速度快 数据迁移案例: 首先数据的迁移绝对不是一朝一夕能够快速迁移完成的 ,如果可以很快完成的 dump便可以搞定,没必要大费周折了. 既然不是一朝一夕能完成的,那么有关键的日志记录表能够良好的反应数据迁移的过程 迁移日志表脚本: DROP TABLE IF

深入解析SQL Server行迁移记录

总长未超过8060字节,变长和定长列存储在同一页/记录中的记录称为行内数据记录.行内记录最常见了,因为一般的记录长度都是在8060字节内的.行内记录理论上都是存放在一个页面中的,这种记录的结构相对简单,格式也相对固定. 行内记录会包含一些常见数据类型的列,如int.char(n).varchar(n).datetime2.real.money等.这些类型的数据有变长的也有定长的,所以在更新变长列的数据时,会使记录长度增大,到超出空闲空间容量时,这样即使此记录小于8060字节,也会造成此记录在这一

Oracle 行链接(Row chaining) 与行迁移(Row Migration)

场景:如果VarChar和VarChar2更经常修改,且修改的数据长度每次都不一样,这会引起“行迁移”现象 概念: 行链接(Row chaining) 与行迁移(Row Migration)当一行的数据过长而不能插入一个单个数据块中时,可能发生两种事情:行链接(row chaining)或行迁移(row migration). 行链接当第一次插入行时,由于行太长而不能容纳在一个数据块中时,就会发生行链接.在这种情况下,oracle会使用与该块链接的一块或多块数据块来容纳该行的数据.行连接经常在插

消除行链接、行迁移

行迁移和行链接是经常接触到的一个概念.行链接是记录太大,一个数据块无法存储,oracle就会将其存储在相链接的块中,如果记录中数据类型包括:LONG.LONG RAW.LOB等数据类型时,行链接则无法避免了,可以在AWR实例活动统计部分的table fetch continued row分析可以看出当前数据库中链接行的数量:行迁移是指在update时,数据块已满,记录更新后记录长度增加了,oracle会将整条记录迁移到新的块中,行迁移后ROWID是不变的.参考ID 102989.1消除行链接和行