oracle数据量巨大表查询时间太长,sqlplus有的不能spool出结果

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle数据量巨大表查询时间太长,sqlplus有的不能spool出结果相关的知识,希望对你有一定的参考价值。

sql如下:
SELECT Count(DISTINCT n),
d
FROM A
WHERE d BETWEEN '20141106' AND '20150405'
GROUP BY d
ORDER BY d;

表A,有三行索引,第一行字段日期d、编号n、单位号I,第二行索引为编号n、单位号I,第三行为日期d、编号n,有分区表,按照每月分区。
因数据量太大(每日表新增数据2.5千万笔,查5个月数据数据量达37.5亿),所以用sqlplus写好定时计划在后台跑并spool出文件,隔一天后发现5个脚本都跑完了,sql经过确认也执行完了,但只导出了2个文件(这个5个脚本结构是一样的,只是具体@到的sql文件和导出文件不一样,并且应该查处的结果均不到500行数据),经查相关资料,有人说是若查询的数据量过于巨大,可能会出不来数据,有的建议指定分区partition查询,但也有的说oracle本身会智能根据where后面的条件查询对应的分区、所以不用特意指定分区。

现在,问题如下:
1、数据量过于巨大的话,是否真的会出不来数据?如果是真的,那么多少条数据或多少G的数据量以上出不来?
2、此表若单独增加一行索引d,只有这一个字段,那么查询的时候速度会不会提上来?
3、现有的三行索引都是多个字段,那么必须同时使用同一行的所有字段才可以算做索引吗?如果不是,如引用第一行的d字段和三个字段都引用有什么区别?
4、想要指定分区partition查询,但也有的人说oracle本身会只能根据where后面的条件查询对应的分区、所以不用特意指定分区,是这样吗?另外,如果是真的,不指定分区表,where 后面日期范围 '20141106' AND '20150405'因不是20141101到20150430,oracle会智能判断出只查14年11月到15年4月这5个分区表吗?
5、想要根据d字段条件查这30多亿数据,有什么好的建议或意见吗?请列出相关sql。谢谢

参考技术A 你的目的是要查询出这三十多亿条数据,并且都导出来;还是在这三十多亿条数据里面快速找出需要的几条数据;如果是前者的话,那就没有捷径可走,只能用分批导出的笨办法了;追问

题干已经写了,“这个5个脚本结构是一样的,只是具体@到的sql文件和导出文件不一样,并且应该查处的结果均不到500行数据”,所以不是你回复的前者,前者exp导出即可。

ORACLE 分区

在建设数据仓库过程中,经常会有大量数据,短时间内表中数据量有限,查询性能还可以,但随着时间的延长,表中数据量迅速增加,查询速度就会变慢,性能下降,这时就要考虑对表进行分区。

 

一、oracle的分区

当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区。表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件上),这样查询数据时,不至于每次都扫描整张表。

 

二、oracle分区的作用

Oracle的表分区功能通过改善可管理性、性能和可用性,从而为各式应用程序带来了极大的好处。通常,分区可以使某些查询以及维护操作的性能大大提高。此外,分区还可以极大简化常见的管理任务,分区是构建千兆字节数据系统或超高可用性系统的关键工具。

分区功能能够将表、索引或索引组织表进一步细分为段,这些数据库对象的段叫做分区。每个分区有自己的名称,还可以选择自己的存储特性。从数据库管理员的角度来看,一个分区后的对象具有多个段,这些段既可进行集体管理,也可单独管理,这就使数据库管理员在管理分区后的对象时有相当大的灵活性。

 

三、oracle的分区包括集中:

1.LIST分区

2.RANGE分区

3.HASH分区

4.范围-散列分区

5.范围-列表分区

 

四、oracle RANGE分区 例子

1.创建表,创建分区

createtable TMP_LXQ_1

(

  PROPOSALNO              VARCHAR2(22),

  STARTDATE               DATE

)

partition byrange(STARTDATE) (

partition part_t01values less than(to_date(‘2008-01-01‘,‘yyyy-mm-dd‘)) ,

partition part_t02values less than(to_date(‘2009-01-01‘,‘yyyy-mm-dd‘)) ,

partition part_t03values less than(to_date(‘2010-01-01‘,‘yyyy-mm-dd‘)) ,

partition part_t04values less than(to_date(‘2011-01-01‘,‘yyyy-mm-dd‘)) ,

partition part_t05values less than(to_date(‘2012-01-01‘,‘yyyy-mm-dd‘)) ,

partition part_t06values less than(to_date(‘2013-01-01‘,‘yyyy-mm-dd‘)) ,

partition part_t07values less than(maxvalue)

);

 

2.查询分区信息

--通过user_tab_partitions 视图查看

SELECT  partition_name, high_value

  FROM user_tab_partitions

 WHERE table_name = ‘TMP_LXQ_1‘;

 

--通过user_part_key_columns视图查看分区表使用的列

SELECT* FROM user_part_key_columns WHERE name = ‘TMP_LXQ_1‘;

 

3.添加分区

ALTERTABLE TMP_LXQ_1

ADD PARTITIONpart_t08 VALUES LESS THAN (to_date(‘2014-01-01‘,‘yyyy-mm-dd‘));

 

4.删除分区

ALTERTABLE TMP_LXQ_1 DROP PARTITIONpart_t07;

--当删除了一个分区,也同时删除了该分区中所有的数据。

 

5.合并分区

--注:不能将分区合并到界限较低的分区。

--下面的SQL,分别将p201001- p201009合并为3个分区

--注:普通的表分区,只能2个分区合成1个分区。3个合成1个的时候,会抱错。

ALTERTABLE TMP_LXQ_1

MERGE PARTITIONSpart_t01,part_t02,part_t03

INTO PARTITIONpart_t03;

--错误:

--ORA-14126:只有<并行子句>可遵循结果分区的说明

 

--合并分区

ALTERTABLE TMP_LXQ_1

MERGE PARTITIONSpart_t01,part_t02

INTO PARTITIONpart_t02;

 

6.拆分分区

 ALTER TABLE TMP_LXQ_1

SPLIT PARTITIONpart_t02 AT(TO_DATE(‘2008-01-01‘,‘YYYY-MM-DD‘))

INTO (PARTITIONpart_t01,PARTITION part_t02);

 

五、oracle LIST分区 例子

drop tabletmp_test1;

create tabletmp_test1

(

comcode varchar2(10)not null,

comnamevarchar2(120) not null,

score decimal(18,2)null

)

PARTITION BY LIST(comcode) (

PARTITIONcomcode_beijing VALUES (‘100000000‘),

PARTITIONcomcode_tianjin VALUES (‘200000000‘),

PARTITIONcomcode_shanghai VALUES (‘300000000‘),

PARTITIONcomcode_hebei VALUES (‘400000000‘,‘410000000‘),

PARTITIONcomcode_shandong VALUES (‘500000000‘),

PARTITIONcomcode_neimenggu VALUES (‘600000000‘)

);

 

insert intotmp_test1

select‘100000000‘,‘北京‘,100 from dual;

commit;

insert intotmp_test1

select‘200000000‘,‘天津‘,100 from dual;

commit;

insert intotmp_test1

select‘300000000‘,‘上海‘,100 from dual;

commit;

insert intotmp_test1

select‘400000000‘,‘河北‘,100 from dual;

commit;

insert intotmp_test1

select‘500000000‘,‘山东‘,100 from dual;

commit;

insert intotmp_test1

select‘600000000‘,‘内蒙‘,100 from dual;

commit;

 

1.添加分区

ALTER TABLEtmp_test1

ADD PARTITIONcomcode_henan VALUES (‘700000000‘);

 

2.删除分区

ALTER TABLEtmp_test1

DROP PARTITIONcomcode_henan;

 

3.拆分分区

ALTER TABLEtmp_test1

SPLIT PARTITIONcomcode_hebei VALUES(‘410000000‘)

INTO (PARTITIONcomcode_shijiazhuang,PARTITION comcode_tangshan);

 

4.合并分区

ALTER TABLEtmp_test1

MERGE PARTITIONscomcode_shijiazhuang,comcode_tangshan

INTO PARTITIONcomcode_hebei;

 

六、问题

select count(*)

  from TMP_LXQ_1 t

 where t.startdate >= date ‘2013-03-01‘;

--37s

select count(*)

  from temp_1 t

 where t.startdate >= date ‘2013-03-01‘;

--9s

 

源表:temp_1

分区后表:TMP_LXQ_1

对这两个表进行同等条件的查询,发现分区后的表的查询速度反而要慢,昨天查询同样的语句,TMP_LXQ_1要用37s,而temp_ciinsuredemand只需要9s。

这两个表中的数据都为9千多万,查询速度都不是很快,但是不清楚为什么分区后的表的查询速度比不分区的表要慢,并且慢这么多。

以上是关于oracle数据量巨大表查询时间太长,sqlplus有的不能spool出结果的主要内容,如果未能解决你的问题,请参考以下文章

oracle数据库如何查询表数据量

ORACLE 大表索引问题:数据量5亿+,做查询,按时间一个月分区,查询会用到3 4个字段,如何见索引

怎么查看oracle数据库数据量大小?

oracle单表的数据量太大该怎么处理

oracle 逻辑对象

多表查询在数据量非常大的时候性能不好,慎用!