`
nydqy
  • 浏览: 37400 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

分区查询问题

阅读更多

表结构如下:
SQL> desc msg_request_history
Name Type Nullable Default Comments
---------- ------------ -------- ------- --------
MSGTYPE NUMBER(8) 0
MSGKEY VARCHAR2(50)
MSGDATE DATE Y SYSDATE
STATUS NUMBER(2) Y 0
按msgdate按天来分区。

SQL> set autotrace traceonly;
SQL>
SQL> select count(*) from msg_request_history
2 where trunc(MSGDATE)= trunc(to_date('20070719','yyyy-mm-dd'))
3 and MSGKEY='11175998';

 

 

执行计划
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=36)
1 0 SORT (AGGREGATE)
2 1 PARTITION RANGE (ALL)
3 2 TABLE ACCESS (FULL) OF 'MSG_REQUEST_HISTORY' (Cost=3 C
ard=1 Bytes=36)
由于where条件中是trunc(MSGDATE),并没有用到partition prune,走的是PARTITION RANGE (ALL)。

SQL> select count(*) from msg_request_history
2 where MSGDATE= to_date('20070719000000','yyyy-mm-dd hh24:mi:ss')
3 and MSGKEY='11175998';


执行计划
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=36)
1 0 SORT (AGGREGATE)
2 1 PARTITION RANGE (SINGLE)
3 2 TABLE ACCESS (FULL) OF 'MSG_REQUEST_HISTORY' (Cost=2 C
ard=1 Bytes=36)
由于where条件中是MSGDATE = ,实现了partition prune,走的是PARTITION RANGE (SINGLE)。

SQL> select count(*) from msg_request_history
2 where MSGDATE between to_date('20070719000000','yyyy-mm-dd hh24:mi:ss') and to_date('20070721000000','yyyy-mm-dd hh24:mi:ss')
3 and MSGKEY='11175998';


执行计划
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=56 Card=1 Bytes=36)
1 0 SORT (AGGREGATE)
2 1 FILTER
3 2 PARTITION RANGE (ITERATOR)
4 3 TABLE ACCESS (FULL) OF 'MSG_REQUEST_HISTORY' (Cost=5
6 Card=1 Bytes=36)

由于where条件中是MSGDATE between and ,同样实现了partition prune,走的是PARTITION RANGE (ITERATOR)。Executes child operations for each partition in the table specified by a range of partition keys。

接下来在msgkey列上创建normal index。
SQL> create index indx_msg_request_history on msg_request_history(msgkey);

Index created

SQL>
SQL> select count(*) from msg_request_history
2 where MSGDATE= to_date('20070719000000','yyyy-mm-dd hh24:mi:ss')
3 and MSGKEY='11175998';


执行计划
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=36)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (BY GLOBAL INDEX ROWID) OF 'MSG_REQUEST_HIS
TORY' (Cost=2 Card=1 Bytes=36)

3 2 INDEX (RANGE SCAN) OF 'INDX_MSG_REQUEST_HISTORY' (NON-
UNIQUE) (Cost=1 Card=21)

发现走的是index range scan,并没有PARTITION RANGE (SINGLE)。

SQL> select trunc(msgdate),count(*) from msg_request_history group by trunc(msgdate);

TRUNC(MSGDATE) COUNT(*)
-------------- ----------
2007-7-19 23368
2007-7-20 23368
2007-7-21 23368
2007-7-23 70104

SQL> select sum(bytes/1024/1024)||'M' from user_segments where segment_name=upper('indx_msg_request_history');

SUM(BYTES/1024/1024)||'M'
-----------------------------------------
4M

SQL> select sum(bytes/1024/1024)||'M' from user_segments where segment_name=upper('msg_request_history');

SUM(BYTES/1024/1024)||'M'
-----------------------------------------
6.4375M

SQL>
SQL> exec COMMON_PARTITION.PROC_DROP_ALL_PARTITIONS('20070731');

PL/SQL procedure successfully completed

SQL> select trunc(msgdate),count(*) from msg_request_history group by trunc(msgdate);

TRUNC(MSGDATE) COUNT(*)
-------------- ----------

SQL> select sum(bytes/1024/1024)||'M' from user_segments where segment_name=upper('msg_request_history');

SUM(BYTES/1024/1024)||'M'
-----------------------------------------
.0625M

SQL> select sum(bytes/1024/1024)||'M' from user_segments where segment_name=upper('indx_msg_request_history');

SUM(BYTES/1024/1024)||'M'
-----------------------------------------
4M

SQL> select trunc(msgdate),count(*) from msg_request_history group by trunc(msgdate);

TRUNC(MSGDATE) COUNT(*)
-------------- ----------

SQL>
SQL> alter index indx_msg_request_history rebuild online;

Index altered

SQL> select sum(bytes/1024/1024)||'M' from user_segments where segment_name=upper('indx_msg_request_history');

SUM(BYTES/1024/1024)||'M'
-----------------------------------------
.0625M

SQL>
在drop分区后发现normal index并没有释放空间,也就是说索引得需重建才行。即使在drop partition的时候带上“update global indexes”也不能回缩索引,看来这个选项只能用在分区索引上。


将normal index给删除掉创建local non-prefixed partition index后执行计划如下:
SQL> create index indx_msg_request_history on msg_request_history(msgkey) local;

Index created

SQL> select count(*) from msg_request_history
2 where MSGDATE= to_date('20070719000000','yyyy-mm-dd hh24:mi:ss')
3 and MSGKEY='11175998';
执行计划
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=36)
1 0 SORT (AGGREGATE)
2 1 PARTITION RANGE (SINGLE)
3 2 TABLE ACCESS (BY LOCAL INDEX ROWID) OF 'MSG_REQUEST_HI
STORY' (Cost=2 Card=1 Bytes=36)

4 3 INDEX (RANGE SCAN) OF 'INDX_MSG_REQUEST_HISTORY' (NO
N-UNIQUE) (Cost=1 Card=8)

可看到性能提高很多。同时对于的索引数据也跟着缩小。
SQL> select trunc(msgdate),count(*) from msg_request_history group by trunc(msgdate);

TRUNC(MSGDATE) COUNT(*)
-------------- ----------
2007-7-19 23368
2007-7-20 23368
2007-7-21 23368
2007-7-23 70104

SQL> exec COMMON_PARTITION.PROC_DROP_PARTITION('20070720');

PL/SQL procedure successfully completed

SQL> exec COMMON_PARTITION.PROC_DROP_PARTITION('20070721');

PL/SQL procedure successfully completed

SQL> exec COMMON_PARTITION.PROC_DROP_PARTITION('20070722');

PL/SQL procedure successfully completed

SQL> exec COMMON_PARTITION.PROC_DROP_PARTITION('20070723');

PL/SQL procedure successfully completed

SQL> select sum(bytes/1024/1024)||'M' from user_segments where segment_name=upper('indx_msg_request_history');

SUM(BYTES/1024/1024)||'M'
-----------------------------------------
1.6875M

SQL> select sum(bytes/1024/1024)||'M' from user_segments where segment_name=upper('msg_request_history');

SUM(BYTES/1024/1024)||'M'
-----------------------------------------
1.875M

SQL>

下面是创建global索引
SQL> create index indx_msg_request_history on msg_request_history(msgkey) global;

Index created
SQL> select count(*) from msg_request_history
2 where MSGDATE= to_date('20070719000000','yyyy-mm-dd hh24:mi:ss')
3 and MSGKEY='11175998';

COUNT(*)
----------
4


执行计划
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=36)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (BY GLOBAL INDEX ROWID) OF 'MSG_REQUEST_HIS
TORY' (Cost=2 Card=1 Bytes=36)

3 2 INDEX (RANGE SCAN) OF 'INDX_MSG_REQUEST_HISTORY' (NON-
UNIQUE) (Cost=1 Card=31)
可看出global index也即normal方式的索引。

发觉有一段话来形容分区表和分区索引特别好,先引用如下(分区表的通俗解释):
普通表呢像一个小学生用的新华字典,分区表呢像一套博士们辞海,在同一个漂亮的盒子里面(表名)有若干本辞海分册(每一册就是一个分区了)。
如果说检索一张普通表就像查新化字典,检索分区表就像查辞海了。具体而言呢,又这么几种方式:
1). 因为你知道你查的内容只会出现在某些分册里面,于是你很快的从辞海盒子里面取出你要的那个册子,不加思索的翻到索引页,根据索引页的指示,你飞快的翻到你的目标页面。取一本本册子呢就叫partition range [inlist] iterator,找索引页当然就是index range scan。如果你不找索引页,准备翻完整本书的找,那就是full table scan了。如果你只找一本册子的,那partition range iterator也就不必了。
2). 哦,你不知道你要查的内容在那本册子里? 那你只好辛苦一点,翻阅所有册子了。这时,你做的动作就叫partition range all.  而对于每本册子言,也许你会找索引页(index scan),也许你想翻遍全册(full table scan)。
3). 也许你发现一册册的打开索引页找内容太繁重了,你突然想起来对你的辞海做个整改。于是你把每册的索引页全都拆了下来,专门装订成一册。每次你想利用索引页找东西时,你就打开这个索引册。从索引册,你就可以找到你要内容在哪一册哪个地方。这就是global index scan. 相对于1,2,就叫local index scan.
4). 你有儿子吗?有一天,你想培训儿子的能力,于是你就找来你儿子给你翻册子,找资料。可是你儿子非得和老子一起找才肯帮你。于是你们父子俩就开始一起检索起辞海来,你查某些册子,他查另一些册子。这就叫partition scan.

分享到:
评论

相关推荐

    龙战于野大数据MR原理启动hive查询表分区.docx

    3. 根据表时间分区查询数据:`hive> select * from table_name where partition_date=‘2020-3-13’ ;` 4. 查看库表:`hive> show databases/table;` 5. 查看表结构:`hive> desc table_name;` Hive查询表分区的MR...

    洗信分区查询

    洗信分区查询.洗信分区查询要得拿去。洗信分区查询

    oracle分区表之hash分区表的使用及扩展

    例如,如果表`equity`按交易日期`trade_date`范围分区,查询特定股票ID在一年内的交易信息时,可能会涉及多个分区,导致跨分区查询,性能可能不佳。而使用Hash分区,相同的股票ID会落在同一分区,提高了查询效率,...

    查看sqlserver表分区数据分布

    在SQL Server中,为了提高大型数据库的管理效率与查询性能,常常会采用表分区技术。通过合理地将一个表的数据分散到多个物理文件或文件组上,可以显著提升数据处理的速度。本文将详细介绍如何查看SQL Server表分区的...

    oracle表分区详解

    - 对于只涉及部分分区的查询,Oracle可以直接定位到相关的分区,避免扫描整个表,从而显著提高查询速度。 - 分区还可以并行处理,进一步加速查询。 ##### 2. 简化管理和维护 - 当表中的数据需要修改或删除时,只...

    MS SQL Server分区表、分区索引详解

    例如,在销售数据中,常见的查询通常是基于日期范围进行的,因此可以选择日期作为分区列。确定了分区列之后,还需要进一步明确分区的数量,即每个分区应包含多少数据,以及这些数据的具体范围。 ##### 2.2 确定是否...

    sql server分区表实例

    分区表将一个大表逻辑上划分为多个部分,每个部分称为一个分区,这些分区可以分别存储在不同的物理位置,以提高查询性能和数据管理效率。在SQL Server中,分区主要基于范围、列表或哈希等策略进行。 首先,`...

    oracel 分区表索引失效的问题

    这种类型的索引通常用于非分区列或者跨分区查询。 **实验验证:** 1. **创建分区表:** 创建了一个基于日期范围的分区表`T_RANGE2`,其中包含三个字段:`id`(主键)、`test_date`(日期字段)、`test1`(字符串...

    ORACLE表自动按月分区步骤

    这里的本地索引是指索引与数据存储在同一分区中,可以显著减少跨分区查询的时间消耗。根据需求,可能需要创建多个索引,以下是一些示例索引创建语句: ```sql CREATE INDEX index_create_time ON USER_ORDER ...

    全面学习分区表及分区索引

    1. 分区策略选择:应根据业务查询模式选择合适的分区策略,确保最常使用的查询条件能利用到分区。 2. 索引设计:索引不是万能的,过多的索引会增加写操作的开销,因此需要权衡查询速度和写入性能。 3. 维护操作:...

    ORACLE分区与索引

    Oracle 分区与索引是数据库管理系统中用于优化大数据查询的关键技术。Oracle 分区是一种将大表和索引分成可管理的小部分,以提高查询效率、维护性和可用性。这种技术适用于处理海量数据,通过将数据分散到不同的存储...

    Oracle 分区表 分区索引

    - **查询模式**:如果大多数查询都涉及对表的一部分数据进行操作,则分区可以减少I/O操作的数量。 - **维护需求**:分区可以简化数据的备份和恢复过程。 #### 三、分区类型 根据不同的应用场景,Oracle提供了多种...

    提高查询速度--分区

    ### 提高查询速度——分区 在数据库管理领域,特别是针对海量数据进行高效管理与查询时,分区技术的应用显得尤为重要。本文将围绕“提高查询速度——分区”这一主题展开讨论,重点介绍分区的基本概念、实现机制及其...

    Oracle分区表详解

    4. **提升查询效率**:对于分区对象的查询操作可以限定于特定的分区范围内,从而加快检索速度。 #### 二、Oracle 分区的优缺点 ##### 优点: - **增强可用性**:即使某个分区出现故障,其他分区的数据仍然可用。 ...

    sqlserver 表分区 详解

    在SQL Server中,表分区是一种优化数据库性能的技术,尤其对于大型数据仓库系统,它能够显著提升数据查询和管理效率。本文将深入解析SQL Server表分区的概念、原理、优点、应用场景,以及实施步骤。 **1. 表分区的...

    深入学习分区表及分区索引(详解oracle分区).docx

    - 分区查询只扫描相关的分区,而非整个表,显著提高查询速度。 - 分区删除和更新操作仅影响相关分区,减少锁定和资源消耗。 - 分区合并和拆分简化了数据管理。 11. **维护与优化**: - 分区交换(Exchange ...

    Oracle表分区详解(优缺点)

    管理方面,分区提供了更高的灵活性,例如,如果某个分区出现问题,可以独立修复,而不会影响到整个表。此外,分区还能实现I/O均衡,通过将不同分区映射到不同的磁盘,减少单一磁盘的负载。 然而,表分区也有其不足...

Global site tag (gtag.js) - Google Analytics