oracle数据库之分区表、索引、表空间

分区

分区表:如果表格的数据量很大,例如有几千万行数据,放在普通表格中查询速度会比较慢,就可以考虑用分区表的方式来存储这么大的数据量(官网的建议是表格的数据超过了2个G的大小的时候)。

分区表只能是一开始就创建好的,不能把一个普通表修改成分区表

下面代码可以查询一个表格有多大

--查询一个表格有多大
select sum(bytes)/1024/1024 表格占用的MB
from dba_extents
where segment_name='大写的表名'
and owner='大写的用户名';

关系型的数据库,在存储和写入数据的时候,都是通过随机IO的方式进行数据写入的,这种方式比较适合数据的写入而不是查询,如果查询的场景很多需要查询速度比较快,就会给大的表格进行分区的设置。

分区的类型

1.散列分区

散列分区是通过数据库的哈希算法来实现的。哈希就是将任何的数据内容转换成数字,用数字除以分区的数量,将相同余数的数据放在同一个分区中。

分区的字段内容没有特征时,一般就是用散列分区。

散列分区表的创建格式如下:

create table 表名(

列名 数据类型 约束条件

......

)partition by hash(要进行分区的列的列名)

   partition 分区名1,

   partition 分区名2,

......

);

--例子:

-- 分区表只能是一开始就创建好的,不能把一个普通表修改成分区表
create table emp_hash(
empno number,
ename varchar2(50),
job varchar2(50),
mgr number,
hiredate date,
sal number,
comm number,
deptno number
) partiton by hash(ename)(
    partition p1,
    partition p2,
    partition p3,
    partition p4
);

--使用代码块的方式添加批量的数据
begin   --放在begin和end之间的我们叫做事务
  for i in 1..100000 loop
      insert into emp_hash select * from emp;
  end loop;
  commit;
end;

-- 查询和比较   按 F5 按键,查看语句的执行计划,查看需要消耗多少资源和时间才能加载出数据
select * from emp_normal where ename='KING';   --2491  30
select * from emp_hash where ename='KING';  --548  7

发现分区表的查询消耗的资源和时间都比普通表要少。

2.列表分区

当分区的字段有大量的重复信息时,就使用列表分区来划分,例如性别、部门、省份、类型......

列表分区表的创建格式如下:

create table 表名(

列名 数据类型 约束条件

......

) partition by list(要分区的列的列名)(

        partition 分区名1 values(分区的值1),

        partition 分区名2 values(分区的值2)

......

);

--例子:

create table emp_list(
empno number,
ename varchar2(50),
job varchar2(50),
mgr number,
hiredate date,
sal number,
comm number,
deptno number
)partition by list(deptno)(
   partition d10 values(10),
   partition d20 values(20),
   partition d30 values(30)
);

--在列表分区中新增一个分区
alter table emp_list add partition d40 values(40);

--删除某个分区
alter table emp_list drop partition d40;
3.范围分区

当字段是时间类型,或者是数值类型(工资,年龄...)时,使用范围分区进行分区表的设置。范围分区的分区划分边界只有小于这种设置方式。

范围分区表的创建格式如下:

create table 表名(

列名 数据类型 约束条件

...

) partition by range(列名)(

partition 分区名字1 values less than (分区的边界值1),

partition 分区名字2 values less than (分区的边界值2),

......

partition 分区名字n values less than (maxvalue)

);

如果范围分区有maxvalue,要添加新的分区,必须要先删除maxvalue的分区再添加

--例子:

create table emp_range(
empno number,
ename varchar2(50),
job varchar2(50),
mgr number,
hiredate date,
sal number,
comm number,
deptno number
)partition by range(sal)(
   partition sal_a values less than (2000),      -- <2000
   partition sal_b values less than (3000),      -- >=2000 and <3000
   partition sal_c values less than (maxvalue)   -- >=3000
);

--如果分区有maxvalue,那么就不能添加新的分区了,必须要先删除maxvalue的分区
alter table emp_range drop partition sal_c;

alter table emp_range add partition sal_c values less than(4000);
alter table emp_range add partition sal_d values less than(5000);
alter table emp_range add partition sal_e values less than(maxvalue);
4.组合分区

用两两不同分区的方式(范围+列表,范围+散列,列表+散列)进行分区表设置的组合,以父子分区的结构来定义表格的,分区中的分区被称为子分区。

组合分区表的创建格式如下:

create table 表名(

列名 数据类型 约束条件

) partition by 父分区类型(列名)

subpartition by 子分区类型(列名)(

     partition 父分区名字1 规则(

        subpartition 子分区名字1 规则,

        subpartition 子分区名字2 规则,

        ),

     partition 父分区名字2 规则(

        subpartition 子分区名字3 规则,

        subpartition 子分区名字4 规则,

        ),

);

--例子:

--用列表+范围两个不同分区方式来构建组合分区表
create table emp_zuhe(
empno number,
ename varchar2(50),
job varchar2(50),
mgr number,
hiredate date,
sal number,
comm number,
deptno number
)partition by list(deptno)
subpartition by range(sal)
(
   partition p_d_10 values(10)(
      subpartition s_10_a values less than (1000),
      subpartition s_10_b values less than (2000),
      subpartition s_10_c values less than (3000),
      subpartition s_10_d values less than (maxvalue)
   ),
   partition p_d_20 values(20)(
      subpartition s_20_a values less than (2500),
      subpartition s_20_b values less than (maxvalue)
   ),
   partition p_d_30 values(30)(
      subpartition s_30_a values less than (1500),
      subpartition s_30_b values less than (3000),
      subpartition s_30_c values less than (maxvalue)
   )
);

分区表格在查询的时候,只有针对分区字段的查询,查询效率才会提升。

和当前表格有关系的一些系统表格

  • select * from user_tables;  查看到当前自己创建的所有表格
  • select * from user_tab_columns;  查看创建的所有表格的字段信息
  • select * from user_tab_partitions;  查看所有的分区表格的信息
  • select * from user_tab_subpartitions;  查看所有组合分区中子分区的信息

单独查看某个父分区的数据:

  • select * from 分区表名 partition (父分区名字);

单独查看某个子分区的数据:

  • select * from  分区表名 subpartition (子分区名字);
select * from emp_list partition(d10);
select * from emp_hash partition(p1);
select * from emp_zuhe subpartition(S_10_A);

单独查询分区,比使用where查询筛选效率更高

-- 单独查询分区,比使用where查询筛选效率更高
select * from emp_list partition(d10);   --705  9
select * from emp_list where deptno=10;  --837  11
分区的操作

新增一个分区:
alter table 分区表名 add partition 分区名 values(分区值);
删除一个分区:删除分区会删除里面的所有的数据
drop table 分区名字 drop partition 分区名;

添加分区,删除分区,截断分区,合并分区,拆分分区,重命名分区

哪种分区类型使用的最多?为什么?

  • 看具体情况:
  • 如果需要进行数据的过期化处理,那么范围分区基本上是唯一的选择。
  • 如果需要数据的均匀分布,那么可以考虑使用HASH分区
  • 如果数据的值可以很好地对应于某个分区,那么就可以考虑使用列表分区
  • 在上面的原则基础上,再结合性能的影响因素,来最终确定使用哪种类型的分区。

索引

索引相当于目录,是对某些特定列中的数据进行排序,生成索引表,在索引里面存储数据和rowid之间的关系,该列作为WHERE条件时,通过ROWID的定位快速的查找行数据,提高查询效率。

索引不是越多越好,索引太多反而会降低表格操作的速度(DML)。

索引的目的:加快表格查询的速度

查询某个表格是否存在索引:select * from user_indexes where table_name='大写的表名';

--查询emp表是否存在索引
select * from user_indexes where table_name='EMP';

索引的类型

Btree索引
1.主键索引

创建表格的时候,如果字段有主键约束的话,那么字段会自动创建一个主键索引。主键索引不能单独创建的,只能根据主键约束来创建。

--给emp表的empno字段增加一个主键约束pk_empno,empno字段自动创建一个主键索引
alter table emp add constraints  primary key(empno);
--删除主键约束pk_empno
alter table emp drop constraints pk_empno;
2.唯一索引

创建表格的时候,如果字段有唯一约束的话,那么字段会自动创建一个唯一索引。唯一索引也可以单独创建,创建的唯一索引,会反过来在表格中生成一个唯一约束。

创建唯一索引:create unique index 索引名 on emp(要创建索引的字段);
删除索引:drop index 索引名;

--给emp表的ename字段增加一个主键约束uk_eanme,ename字段自动创建一个唯一索引
alter table emp add constraints uk_ename unique(eanme);
alter table emp drop constraints uk_ename;  --删除唯一约束

--单独创建唯一索引
create unique index idx_ename on emp(ename);
drop index idx_ename;
3.普通索引

表格的字段需要经常被查询,但是字段数据又没有什么特征。

--创建一个普通索引idx_mgr 
create index idx_mgr on emp(mgr);
--删除索引
drop index idx_mgr ;
4.组合索引

表格的某些字段,在查询的时候经常需要放在一起当成多个条件共同进行查询。
创建组合索引:create index 索引名 on emp(字段1,字段2...);

--组合索引的字段可以是N个
create index idx_n_d on emp(ename,deptno);

如果我们创建了一个组合索引 (a,b,c),那么在数据库内部,会有几个子索引:

a    ab    ac     abc

哪个字段写在组合的最前面,那么查询的时候,这个字段就必须存在。

5.函数索引

当某个字段,都是需要先进行函数的计算然后将计算结果拿出来进行查询的。如emp表中的haredate字段,我们一般都把它转成字符类型来用

--给emp表的hiredate字段创建函数索引
create index idx_year on emp(to_char(hiredate,'yyyy'));
位图索引(bitmap索引)

当某个字段里面的数据全部都是重复的,例如性别、省份、类型、部门......,对这些字段进行查询,就可以创建位图索引。

--给emp表的deptno字段创建位图索引
create bitmap index bit_dept on emp(deptno);

分区表中的索引(分区索引)

1.全局索引:global

全局索引中不能创建位图索引。

如果删除了分区表中的某个分区(drop partition),那么全局索引会失效,在查询时就无法使用了。

索引因为删除分区失效之后,可以通过rebuild来重建:alter index 索引名 rebuild;

2.本地索引:local

本地索引中不能创建唯一索引。

不同的索引一般用在什么场景下?

  • 主键索引:当某数据不能重复,也不能为空,建立PRIMARY KEY主键时(索引自动建立)
  • 唯一索引:当某列数据不能重复,但可以为空,建立UNIQUE CONSTRAINT唯一约束时(索引自动建立)。
  • 组合索引:当多列经常一起出现在WHERE条件中,创建索引。
  • 位图索引:当一列有大量重复数据时建立。
  • 函数索引:在WHERE 条件语句中包含函数或表达式时建立。

​​​​​​​普通索引和位图索引有什么区别?

  • 普通索引:列的内容没有什么特点,但是经常需要被进行查询创建:
  • 位图索引:列中有非常多的重复的值时候创建。例如某列保存了 “性别”信息创建:

​​​​​​​索引在什么情况下会失效?

  • 1.筛选条件的左右两边,数据类型不一致导致了数据的隐性转换,索引就会失效;
    • select * from emp_idx where to_char(hiredate,'yyyy')=1981;
  • 2.在使用索引的时候,在索引的字段上进行数据计算
    • select * from emp_idx where sal+1000=800;
  • 3.对空值进行查询
    • select * from customers_info where curstomer is null;
  • 4.取反查询 != not 
    • select * from customers_info where not curstomer='冯丹';
  • 5.模糊查询 like 模糊的部分在查询字符串的后面就会走索引,在前面就不会有 
    • select * from customers_info where curstomer like '%丹'
  • 6.如果查询的字段,结果集的行数,占了表格行数的一定比例,可能就不会走索引了。
  • 7.组合索引,在筛选数据的时候,没有使用组合里面的第一个字段,(a b c)没有使用a,那么索引也会失效。
  • 8.全局的分区表格索引,删除了分区,索引也会失效。
  • 9.如果字段使用了函数,但是函数没有定义为函数索引,字段的索引也会失效。

​​​​​​​索引的优缺点?

  • 索引优点:创建唯一索引,可以保证数据库中每一行数据的唯一性;可以加快数据的检索速度;可以加速表和表之间的连接
  • 索引缺点:创建和维护索引要耗费大量时间;索引会占物理存储空间;对表中数据进行操作,索引也要动态维护;

​​​​​​​哪些列该建立索引?哪些列不应建立索引?

  • 建立索引经常需要搜索、排序的列;关联字段
  • 不该建立索引很少使用的列;只有很少数据值的列;定义为TEXT,IMAGE,BIT数据类型的列;

​​​​​​​唯一索引和主键索引有什么区别

  • 主键是不能自己独立创建,和主键约束一起创建的;
  • 唯一可以和约束一起创建,也可以单独创建。
  • 主键是保证字段不能空不重复,唯一只能保证不重复。

​​​​​​​索引中本地索引和全局索引的区别是什么?

  • 本地索引不能创建唯一索引的类型,因为每个小的索引只能保证每个分区的数据是唯一的,不能保证整个表格的数据是唯一的。
  • 全局索引不能创建位图索引的类型,统一管理的索引,无法对整个表格中,每个独立的分区的数据进行识别和判断。

​​​​​​​怎么查看一个表格有哪些不同的索引?

  • select * from user_indexes where table_name='表名';

表空间

表空间是一个逻辑概念,在一个表空间里面会有多个数据文件,在数据文件中,保存表格和数据等不同的内容。

数据库里面,默认的表空间的名字叫做 USERS。

创建一个自己的表空间:

  • create tablespace 空间名字 datafile '硬盘的位置和文件的名字' size xxM;

给已经存在的表空间追加新的数据文件:

  • alter tablespace 空间名字 add datafile '硬盘的位置和文件的名字' size xxM;

--例子:

--创建一个表空间ts_1
create tablespace ts_1 datafile 'E:/ora_files/t01.dbf' size 50M;
--给表空间ts_1追加新的数据文件
alter tablespace ts_1 add datafile 'E:/ora_files/t02.dbf' size 50M;

create table test17(
userid number,
username varchar2(50)
) tablespace ts_1;   --创建test17表放到指定ts_1表空间中

create table test18(
userid number,
username varchar2(50),
age number
)partition by range(age)
(
   partition age_1 values less than(30),
   partition age_2 values less than(maxvalue)
) tablespace ts_1;  --创建test18范围分区表放到指定ts_1表空间中


create table test18(
userid number,
username varchar2(50),
age number
)partition by range(age)
(
   partition age_1 values less than(30) tablespace ts_1,
   partition age_2 values less than(maxvalue) 
);  --不指定表空间,创建test19表放到默认表空间USERS中

在新增数据的时候,如果提示表空间对应的文件满了,有两种方法:

  1. 再次新增一个数据文件
  2. 修改数据文件的大小
  • alter database datafile '数据文件的位置和名字' resize xxM;
alter database datafile 'E:/ora_files/t02.dbf' resize 100M;

删除表空间:

  • drop tablespace 表空间名字;
  • drop tablespace 表空间名字 including contents;

如果表空间被分区表的某个分区使用了,还需要先删除分区表或者是这个单一分区,才能去删除表空间

drop tablespace ts_1 including contents;

查看表空间和数据文件的基本信息:

  • select * from dba_data_files;

查看有哪些表空间:

  • select * from user_tablespaces;

--查看表空间和数据文件的信息:

--查看表空间的使用总大小
select sum(a.BYTES-b.BYTES)/1024/1024||'M' from dba_data_files a join dba_free_space b 
on a.file_id=b.file_id
where b.tablespace_name='TS_1';

--查看数据文件每个文件的使用的大小
select file_name,(a.BYTES-b.BYTES)/1024/1024||'M' from dba_data_files a join dba_free_space b on a.file_id=b.file_id
where b.tablespace_name='TS_1';

  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

30+11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值