달력

08

« 2018/08 »

  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
.. .. ..

 

 

[펌] : http://ideacoop.tistory.com/615

 


오렌지에서 실행할때..

우선 Schema Browser 에서 해당 프로시저를 찾아서 더블클릭해주고
디버그모드로 컴파일 하고
Debug>Start 를 하면 창이 하나 뜨는데
다음과 같은 문자을 넣어주고 해당 창의 Start 버튼을 누른다.

DECLARE
v_OutArg1 varchar2(100);
v_OutArg2 varchar2(100);
v_OutArg3 varchar2(100);
BEGIN
유저.패키지.프로시저(v_OutArg1,v_OutArg2,v_OutArg3);
END;

이때 보고자 하는 변수명은 드래그 드랍하여 Watch... 쪽에 끌어놓으면 볼수 있다.

만일 서버 Output 이 가능하다면
dbms_output.put_line(v_OutArg1);
를 추가로 기술할 경우 그 내용을 실행이 끝난뒤 보여 준다.


 

Ref. Contents : 1 Writing Time : 2006.02.09 15:46 from 202.133.27.224

 

Title

Count

Date

Writer

 

  [ORACLE] 프로시저 SQLPlus 에서 실행

403

2006.02.09

hasspark

=>

  [ORACLE] 프로시저 오렌지에서 실행

591

2006.02.09

hasspark

 

 

.
Posted by .07274.

댓글을 달아 주세요

2014.01.06 16:07

CentOS 에 Oracle 설치하기 I.lib()/I.lib(Oracle)2014.01.06 16:07

.. .. ..

http://blueray21.tistory.com/21

.
Posted by .07274.

댓글을 달아 주세요

.. .. ..

Redmine 에서 Back-End 로 사용하는 DB중에는 Oracle 이 공식적으로는 없다.

 

하지만 블로그 링크를 통해 아래 경로를 추천하였으며 그에 대한 정리를 한다.

 

블로그 경로 : [http://matthewrupert.net/2011/03/11/running-redmine-with-an-oracle-backend/]

 

1. Oracle sees ” and “null” as the same thing.
The biggest issue is the fact that Oracle see ” and ‘null’ as the same thing. That said, there are a few setup scripts that will need modified. I went through db/migrate/001_setup.rb and looked for everything that sets a default value of ” and told it to allow nulls for any such column.

For example, the users table is created like this:

create_table “users”, :force => true do |t|
t.column “login”, :string, :limit => 30, :default => “”, :null => true
t.column “hashed_password”, :string, :limit => 40, :default => “”, :null => true
t.column “firstname”, :string, :limit => 30, :default => “”, :null => true
t.column “lastname”, :string, :limit => 30, :default => “”, :null => true
t.column “mail”, :string, :limit => 60, :default => “”, :null => true
t.column “mail_notification”, :boolean, :default => true, :null => false
t.column “admin”, :boolean, :default => false, :null => false
t.column “status”, :integer, :default => 1, :null => false
t.column “last_login_on”, :datetime
t.column “language”, :string, :limit => 2, :default => “”, :null => true
t.column “auth_source_id”, :integer
t.column “created_on”, :timestamp
t.column “updated_on”, :timestamp
end

…and versions:

create_table “versions”, :force => true do |t|
t.column “project_id”, :integer, :default => 0, :null => true
t.column “name”, :string, :limit => 30, :default => “”, :null => true
t.column “description”, :string, :default => “”
t.column “effective_date”, :date, :null => true
t.column “created_on”, :timestamp
t.column “updated_on”, :timestamp
end

I’m simply allowing nulls where before null was no longer accepted. This shouldn’t be a problem, its just a lacking database constraint. I’ll definitely follow up if it does become a problem.

There are a few other places where you’ll have to make similar changes:

  • 074_add_auth_sources_tls.rb
  • 091_change_changesets_revision_to_string.rb
  • 108_add_identity_url_to_users.rb
  • 20091017214336_add_missing_indexes_to_users.rb

-- 오라클에서는 " 라는 값도 null로 인식한다는 뜻 같은데.. 정확하게는 알수가 없어 위에 시키는대로 따라하였다.

    20091017214336_add_missing_indexes_to_users.rb 파일에서는 딱히 수정할것이 없어 수정하지 않았다.

 

2. Version Effective Date:
Oracle won’t like the syntax of 048_allow_null_version_effective_date.rb. I simply removed this file (it appears that this was a later change in Redmine) and made the version effective data column nullable in 001_setup.rb like this:

create_table “versions”, :force => true do |t|
t.column “project_id”, :integer, :default => 0, :null => true
t.column “name”, :string, :limit => 30, :default => “”, :null => true
t.column “description”, :string, :default => “”
t.column “effective_date”, :date, :null => true
t.column “created_on”, :timestamp
t.column “updated_on”, :timestamp
end

 

-- 오라클에서는 필요 없는 기능이라는 의미 같은데.. 일단 삭제하라는 파일은 삭제하였고 versions 부분은 1번에서

    동일하게 변경하였기 때문에 수행하지 않았다.

 

3. The UTF-8 Problem
Assuming your Oracle database uses AL32UTF8, you’ll want to do something like this in environment.rb:

ENV['NLS_LANG']=’american_america.AL32UTF8′

 

-- UTF-8 을 사용할때의 옵션같다. 저는 한글을 쓰기 때문이 이 기능에 대해서 적용하지 않았습니다

 

4. Oracle 30-character limitation on table names
Oracle limits table names to 30 characters in length. This is a problem in one particular Redmine db migration script: 107_add_open_id_authentication_tables.rb
I changed this file to use smaller table names:

class AddOpenIdAuthenticationTables < ActiveRecord::Migration
def self.up
create_table :open_id_auth_associations, :force => true do |t|
t.integer :issued, :lifetime
t.string :handle, :assoc_type
t.binary :server_url, :secret
end

create_table :open_id_auth_nonces, :force => true do |t|
t.integer :timestamp, :null => false
t.string :server_url, :null => true
t.string :salt, :null => false
end
end

def self.down
drop_table :open_id_authentication_associations
drop_table :open_id_authentication_nonces
end
end

 

-- 글자수 제한 관련한 수정이다. 위와 같이 따라하면 된다.

 

5. A problem with the Activity Tab
There a problem with Oracle CLOB String comparison (as in, you can’t compare a CLOB to a String). This is documented here: http://www.redmine.org/issues/3699
Unfortunately, the Redmine response is always “Oracle is not supported.” Hey, I don’t care for being stuck with Oracle either, but some of us are. Anyway, you can take care of this problem with a simple change to the comparison. Change redmine/app/models/journal.rb:

acts_as_activity_provider :type => ‘issues’,
:permission => :view_issues,
:author_key => :user_id,
:find_options => {:include => [{:issue => :project}, :details, :user],
:conditions => “#{Journal.table_name}.journalized_type = ‘Issue’ AND” +
” (#{JournalDetail.table_name}.prop_key = ‘status_id’ OR length(#{Journal.table_name}.notes) > 0)”}

 

 

-- 시키는대로 변경한다.

 

8. Change the sequences
Before you get moving, you’re probably going to want to fix the table sequences, setting them to start at 1. This is just a matter of preference, but at least for the ISSUES_SEQ, since the unique ID is used to identify the ticket, it makes sense to start with lower numbers. For some reason that I don’t understand (yet), Oracle 11 starts sequences at 10,000. I recommend doing this:

DROP SEQUENCE REDMINEUSER.ISSUES_SEQ;
CREATE SEQUENCE ISSUES_SEQ
START WITH 1
MAXVALUE 9999999999999999999999999999
MINVALUE 1
NOCYCLE
CACHE 20
NOORDER;
Now your tickets will start with lower numbers. As far as other sequences go, it doesn’t matter too much, since we generally don’t view the id columns.

 

-- 시키는대로 따라한다.. (사실 난 안해도 잘돌아가서 안했지만;;)

 

9. Annoyingly Short VARCHAR2 Defaults
The default VARCHAR2 setting is going to be VARCHAR2(255). When it comes to certain fields, such as the project description, this is a little on the short side. I went ahead and modified the column width myself:

alter table PROJECTS modify description VARCHAR2(4000);

commit;

 

//2013.12.10 추가. 아래 테이블의 컬럼값도 변경되야 한다.

alter table journal_details modify VALUE VARCHAR2(4000);
alter table journal_details modify OLD_VALUE VARCHAR2(4000);

 

-- 이미 버그로 인식해서 수정했던 부분이었기 때문에 적용하진 않았지만 꼭 해둘필요가 있다.

 

10. Database Trigger Needed to Copy Workflows
When creating a Tracker, Redmine allows a user to “Copy from existing workflow.” (I.e., You can copy the Tracker workflow from an existing Tracker, making the process of adding a new Tracker much more quick.) This creates a possible error when inserting the new workflow into the Workflows table because for some reason (and I’m not yet sure why), no trigger was created on the Oracle database. Without this trigger you will see a “Cannot insert null” error in your production log file if you attempt to copy a workflow. To get around this problem it is easy enough to create a trigger on the Workflows table:


CREATE OR REPLACE TRIGGER workflows_before_insert
BEFORE INSERT
ON WORKFLOWS
FOR EACH ROW
BEGIN
if :new.id is null then
SELECT workflows_seq.nextval INTO :new.ID FROM dual;
end if;
END;
/

 

-- 영어 해석이 되지 않아 무슨소린지 몰라서 일단 생성만 해두었다.

11. Database connection
Finally, database.yml will end up looking something like this:

production:
adapter: oracle_enhanced
database:
host:
port: username: redmine_db_user
password: redmine_db_pass

These changes are very important to note should you ever have to upgrade Redmine.

 

--위같이 설정하면 끝!!!!!!! 인줄 알았지만 버젼 업은 되었지만 블로그 글은 업이 되지 않았다는것.

  추가적으로 아래 내용도 적용한다.

 

12. app/views/issues/_attributes.html.erb 수정

 

 

 

- <p><%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date') %><%= calendar_for('issue_start_date') if @issue.leaf? %></p>
+ <p><%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date'), :value => @issue.start_date ? @issue.start_date.strftime(Setting.date_format) : "" %><%= calendar_for('issue_start_date') if @issue.leaf? %></p>

-- 윗줄의 내용을 아래와 같이 변경한다. start_date 뿐만 아니라 due_date 도 같이 변경해준다.

-- 이슈 업데이트 문제를 해결해 준다.

 

13. config/init..../oracle.rb 추가 (파일이 없으니 추가한다!) 

ActiveSupport.on_load(:active_record) do
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
self.emulate_dates_by_column_name = true
end
end
-- 안되던 간트차트가 뿅하고 나올것이니라

 

14. app/models/query.rb
수정
def has_column?(column)
+ return false if !column_names.kind_of?(Array)
column_names && column_names.include?(column.is_a?(QueryColumn) ? column.name : column)
end

-- return 줄을 추가한다.

 

이상입니다.

댓글 및 질문 받지만 도와드릴수 있을지는 미정입니다^^;

.
Posted by .07274.

댓글을 달아 주세요

2013.09.27 16:42

Oracle LAG 사용 방법 I.lib()/I.lib(Oracle)2013.09.27 16:42

.. .. ..

요약 :

 

LAG(컬럼1) OVER (ORDER BY 정렬컬럼1) 

 

     ===> 컬럼 1의 다음 Row 데이터

 

 

[출처] [Oracle] 오라클 LEAD, LAG|작성자 시어

 

전월대비 또는 전일대비 같은 Self Join 이나 Sum_Case 문을 사용하던것을

 

오라클 LAG 또는 LEAD 함수로 처리 한다.

 

이거쓰면 게시판의 이전 다음글을 좀 쉽게 구현할 수 있을까??

Lead 함수는 해당 파티션내의 바로 다음 Row 의 데이터를 참조할 수 있고

 

Lag 함수는 해당 파티션내의 바로 위의 Row 데이터를 참조할 수 있다.

 

 

SELECT

DAY

, MONEY

, ROUND( ( LAG(MONEY) OVER (ORDER BY DAY) - MONEY )/ MONEY *100 , 1) As BENEFIT_RATE
FROM

(
SELECT '20010901' As DAY, 1000 As MONEY FROM DUAL

UNION ALL
SELECT '20010902' As DAY, 990 As MONEY FROM DUAL

UNION ALL
SELECT '20010903' As DAY, 900 As MONEY FROM DUAL
);

결과는

DAY MONEY BENEFIT_RATE
20090901 1000
20090902 990 1
20090903 900 10

 

 

 

 

.
Posted by .07274.

댓글을 달아 주세요

  1. Favicon of http://its3am.net BlogIcon RynnA 2013.09.29 23:23 신고  댓글주소  수정/삭제  댓글쓰기

    꺅. 돌아왔다고... 인사드리러 왔다가, 이런 공격(?)을 받다니!!!!
    쿡쿡쿡. 잘 지내고 계셨죠?

    • Favicon of http://a07274.tistory.com BlogIcon .07274. 2013.10.11 17:49 신고  댓글주소  수정/삭제

      네! 조심스러워 저번 댓글에 아직 답장도 못했는데 또다른 반가운 소식을 주시네요^^
      일단 저는 잘 지내고요~! 린아님도 잘 지내시고 돌아오신건지 가봐야 겠네요^^
      (이런 공격(?) 이란 혹시 광고때문 일까요? 흐음..)

.. .. ..

[펌] : http://cafe.daum.net/dbmsclub/LLPP/21?docid=1Ex4ELLPP2120091217141531

 

일반적으로 텍스트 데이터의 적재프로그램을 만들다보면, 기존에 있는 자료에 대해서는 업데이트를 수행하고 신규자료인 경우는 등록을 해야하는 업무가 있습니다. 비단, 적재뿐아니라 통계분석 데이터의 생성인 경우에도 이 내용은 해당이 되는데 보통은 upsert라고 해서 delete and insert기법을 많이들 활용하십니다만, 오라클에서는 merge구문을 지원합니다. 이 문장은 oracle이 알아서 update할것인지 insert할것인지 데이터를 선별해서 처리를 해주게 되는데요. 뭐 많이 어려운 구문도 아니고 사용하기도 간편하니까 어떤 방식으로 사용할 수 있는지 확인해봅시다.

 

문장 표준) MERGE INTO TARGET_TABLE A /* 실제 데이터가 저장될 TARGET TABLE입니다. */

USING (SELECT COL_A,COL_B... /* TARGET에 저장할 데이터가 있는 원본 데이터가 있는 테이블 또는 QUERY입니다 */

FROM SOURCE_TABLE

WHERE 조건들....) B

ON ( A.COL_A = B.COL_A ) /* 원본과 타겟의 컬럼이 어떤 값으로 중복되는지 체크할 조건입니다. 이 값으로 */

/* 오라클은 업데이트해야할지 INSERT해야할지를 결정합니다. */

WHEN MATCHED THEN /* 만약 조건이 같은 경우 UPDATE할 내용을 기술합니다. */

UPDATE SET

A.COL_B = B.COL_B

,A.COL_C = B.COL_B

WHEN NOT MATCHED THEN /* INSERT해야할 내용을 기술합니다. */

INSERT (COL_A,COL_B,COL_C....)

VALUES ( B.COL_A,B.COL_B,....);

위의 형식으로 구문을 사용하시게 되면, 오라클은 데이터가 UPSERTED되었다고 결과가 나오게 되고, 몇개의 ROW가 UPDATE또는 INSERT되었는지 확인하실 수 있습니다.

 

예제)

MERGE INTO DATA1004_6 M
USING (SELECT TRADE_DATE AS YMD
,MIN(REAL_CLASSCODE||LPAD(REPLACE(UNIT_SIZE,' ',''),7,'0')||UNIT_CODE) PM_KEY
,REAL_CLASSCODE
,REPLACE(UNIT_SIZE,' ','') AS UNITSIZE /* RPAD쓰지 않아도 CHAR TYPE이라 자동 ' '추가됨 */
,UNIT_CODE AS UNITCODE
,GRADE_CODE AS GRADECODE
,AVG(JOSA_PRICE) AS P_MEAN
FROM SRC_DATA1004
WHERE TRADE_DATE >= in_st_dt
AND TRADE_DATE <= in_ed_dt
AND JOSA_GUBUN_CODE = '6' -- 도소매
AND JOSA_PRICE <> 0
GROUP BY TRADE_DATE,REAL_CLASSCODE,UNIT_SIZE,UNIT_CODE,GRADE_CODE) T
ON ( M.YMD = T.YMD
AND M.PM_KEY = T.PM_KEY
AND M.GRADECODE = T.GRADECODE)
WHEN MATCHED THEN
UPDATE SET
M.P_MEAN = T.P_MEAN
WHEN NOT MATCHED THEN
INSERT (YMD,PM_KEY,REAL_CLASSCODE,UNITSIZE,UNITCODE,GRADECODE,P_MEAN)
VALUES (T.YMD,T.PM_KEY,T.REAL_CLASSCODE,T.UNITSIZE,T.UNITCODE,T.GRADECODE,T.P_MEAN);

위 예제의 경우는 SRC_DATA1004 테이블의 데이터를 읽어서 해당하는 값이 DATA1004_6에 존재하는 경우는 UPDATE하고

존재하지 않는 경우는 INSERT하는 프로그램입니다. 일주일치를 수행하는데 약 1만건 정도인데, 2-4초정도 걸리는군요.

 

프로그램코딩시 유의할 오류유형)

1.ORA-30926 에러가 발생하는 경우

ORA-30926 원본 테이블의 고정 행 집합을 가져올 수 없습니다.

ORA-30926 unable to get a stable set of rows in the source tables

- MERGE 를 사용하는 경우

1) INTO 절에 사용되는 테이블에 Primary Key 를 사용하는 경우
즉 INSERT 구문에서 DUPLICATE가 발생하거나 UPDATE 에 MULTI
ROW가 UPDATE되는 경우

2) ON 구문에서 UPDATE되는 ROW가 1개 이상일 경우
즉 ON 구문에서 맞는 테이블 값이 하나 이상일 경우

2.ORA-00001 에러가 발생하는 경우

이 에러는 TARGET이 되는 테이블에는 중복건이 없어서 UPDATE를 할려고 했는데,

SOURCE테이블 자체에서 데이터가 중복건이 있어서 두번INSERT하려고 하다가 문제가 발생합니다.

보통 문자타입이나 사이즈를 잘못잡아서 INSERT할 대상자체를 중복인지 아닌지 모르는 경우에

발생하게 되므로, TRIM처리를 해서 비교하시든 파일자체에 중복이 있는지 확인을 하시든 하는 방법으로

에러를 처리하실 수 있습니다.

.
Posted by .07274.

댓글을 달아 주세요

  1. 토끼주인 2014.11.07 16:43 신고  댓글주소  수정/삭제  댓글쓰기

    글 감사합니다. 그런데 마지막 줄에 '이 에러는 TARGET이 되는 TABLE에는 중복건이 없어서 UPDATE를 할려고 했는데'라고 하신 거, UPDATE가 아니라 INSERT죠?

.. .. ..
@ 타계정에도 접근가능하게끔 시퀀스에 권한을 준다.

grant [select,sequence,alter] on 소유계정.시퀀스 to 대상계정;


- select : currval과 nextval을 사용할 수 있는 권한
- alter : sequence 변경권한을 줌
- sequence : alter와 select를 포함

 

.
Posted by .07274.

댓글을 달아 주세요

2012.11.21 16:59

오라클 커넥션 정보 I.lib()/I.lib(Oracle)2012.11.21 16:59

.. .. ..

[펌] : http://tiamo.tistory.com/3

 

SELECT count(*)
FROM v$session s
WHERE s.username IS NOT NULL
AND NVL (s.osuser, 'x') <> 'SYSTEM'
AND s.TYPE <> 'BACKGROUND';



SELECT /*+ rule */
s.status "Status", s.serial# "Serial#", s.TYPE "Type",
s.username "DB User", s.osuser "Client User", s.server "Server",
s.machine "Machine", s.module "Module", s.terminal "Terminal",
s.program "Program", p.program "O.S. Program",
s.logon_time "Connect Time", lockwait "Lock Wait",
si.physical_reads "Physical Reads", si.block_gets "Block Gets",
si.consistent_gets "Consistent Gets",
si.block_changes "Block Changes",
si.consistent_changes "Consistent Changes", s.process "Process",
p.spid, p.pid, s.serial#, si.sid, s.sql_address "Address",
s.sql_hash_value "Sql Hash", s.action
FROM v$session s, v$process p, sys.v_$sess_io si
WHERE s.paddr = p.addr(+)
AND si.sid(+) = s.sid
AND s.username IS NOT NULL
AND NVL (s.osuser, 'x') <> 'SYSTEM'
AND s.TYPE <> 'BACKGROUND'
ORDER BY 3

.
Posted by .07274.

댓글을 달아 주세요

.. .. ..

vi test

file  = 20120620_TB_KT_TALLEHPOINTAUTH.dmp
log   = 20120620_TB_KT_TALLEHPOINTAUTH.log
tables     = cpass.KT_TMCHT_TRAN_INFO
query     = "WHERE  TO_DATE(JOB_DT, 'YYYYMMDD') >  TO_DATE('20120301', 'YYYYMMDD')"

 

exp 아이디/패스워드 parfile=vi로만든 파일이름

 

 

 

 

참고자료

[펌] :  https://kr.forums.oracle.com/forums/thread.jspa?messageID=1698906

 

제품 : ORACLE SERVER

작성날짜 : 2004-03-17

EXPORT 시 QUERY OPTION에 대한 사용 예(ORACLE 8I 이상)
============================================

PURPOSE
============
oracle 8i에서 export 시 query option에 대한 사용 예


8i에서 export의 query syntax 를 이용하여 table data의 한 부분만 exporting 이 가능


- 8i 에서 select 문장의 where 절을 사용하는 것처럼 export 시에 부분적으로 table data 를 받아 낼수 있는 기능을 소개 한다.
- Direct 옵션은 사용될 수 없다..
- where 절에 해당하는 export utility는 query parameter 를 사용한다.

UNIX syntax:



- Example:
1.SCOTT.Emp table의 ename 이 JAME과 비슷한 이름의 data 를 export ..
exp scott/tiger query=\"where ename like \'JAME%\'\" tables=emp file=exp.dmp log=exp.log


2. employee와 cust table에서 new york 주의 data 만 export ..
exp scott/tiger query=\"where st=\'NY\'\" tables=(employee,cust) file=exp.dmp log=exp.log

query 문장에서 UNIX reserved characters( ", ', ,< .. 등) 를 사용하는 경우에는 escape ('\') 을 반드시 사용해야 한다.
예)query=\"where JOB = \'SALESMAN\' and salary \< 1600\"

더 중요한 것은 command line에서 export option을 사용할때는 반드시 escape 이 있어야 하나
parfile을 사용할때는 eacape이 불필요하다.

예를 보면 .. p라는 이름의 file을 다음과 같이 생성
tables=emp query="where job='SALESMAN'"

parfile을 이용해서 export 를 실행해 보면
[rmtdchp6]/apac/rdbms/64bit/app/oracle/product/9.2.0> exp scott/tiger parfile=p

Export: Release 9.2.0.4.0 - Production on Wed Mar 17 00:12:34 2004

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Connected to: Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
Export done in US7ASCII character set and AL16UTF16 NCHAR character set
server uses KO16KSC5601 character set (possible charset conversion)

About to export specified tables via Conventional Path ...
. . exporting table EMP 4 rows exported
와 같이 정상 처리 됨을 알수 있다.

만일 command line에서 위의 내용을 실행하게 되면 다음과 같이 error 를 만난다.
exp scott/tiger tables=emp query="where job='SALESMAN'"

LRM-00101: unknown parameter name 'job'

EXP-00019: failed to process parameters, type 'EXP HELP=Y' for help
EXP-00000: Export terminated unsuccessfully

command line에는 query 내에 single(')나 double quotes(") 를 사용한다면 반드시 double quotes(") 를 사용하여
query 문을 묶어야 한다.그러나 query 내에서 single ('')나 double quotes(") 를 사용하지 않는다면 single quotes (')을 사용하여
query 문을 수행할 수도 있다..

다음 예를 보면..
1>exp scott/tiger tables=emp query=\'where deptno=20\'

Export: Release 9.2.0.4.0 - Production on Wed Mar 17 00:22:00 2004

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Connected to: Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
Export done in US7ASCII character set and AL16UTF16 NCHAR character set
server uses KO16KSC5601 character set (possible charset conversion)

About to export specified tables via Conventional Path ...
. . exporting table EMP 4 rows exported

2>exp scott/tiger tables=emp query=\'where job=\'SALESMAN\'\'

LRM-00112: multiple values not allowed for parameter 'query'

EXP-00019: failed to process parameters, type 'EXP HELP=Y' for help
EXP-00000: Export terminated unsuccessfully

즉.. 정리를 하자면
command line에서 query 내에 '," 을사용하지 않는 다면 '나 " 으로 query option을 사용할수 있다
query=\'where deptno = 20\'
query=\"where deptno = 20\"
query=\'where deptno \< 2\'
(이 경우 single 이나 double quotes 을 둘다 사용할수 있다.)

parfile을 사용하는 경우에는 다음과 같이 단순하게 사용이 가능하다.
query='where deptno = 20'
query="where deptno = 20"
query='where deptno < 20'


WINDOWS NT / 2000 와 NETWARE syntax:


다음의 자료를 참조바란다.

Example:

EXP demo/demo tables=emp file=exp1.dmp query="""where deptno>30"""

double quotes(") 를 둘러 싸는 경우에는 space 가있으면 안된다.

parfile의 사용은 다음과 같이 하시면 됩니다.

file=exp66.dmp
query="where deptno > 20"
tables=(emp)
log=log66.txt
userid=scott/tiger


Explanation


Windows NT or Win2000의 경우 command line에서는 3 double quotes 이 필요하고
'PARFILE 을 사용하는 경우에는 double quotes(") 한번만 필요함

Reference Documents


Oracle8i Utilities guide
Note:91864.1

.
Posted by .07274.

댓글을 달아 주세요

.. .. ..

[펌]

http://energ.tistory.com/entry/%ED%85%8C%EC%9D%B4%EB%B8%94%EB%82%B4-%EC%A1%B0%EA%B1%B4%EC%97%90-%EB%A7%9E%EB%8A%94-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A7%8C-export

 

.
Posted by .07274.

댓글을 달아 주세요

.. .. ..

[펌] : http://blog.daum.net/warmfeel/82

 

I. 오라클 파티션 정의

1. 파티션 개요
오늘날 기업에서 관리하는 데이터는 수백테라 바이트에 이르는 데이터베이스를 관리한다.
하지만 이런 데이터들 중 몇몇의 Big Transaction Table이 거의 모든 데이터를 가지고 있고
나머지 테이블들은 이 Big Transaction Table을 경유하여 액세스 하는 용도로 사용된다.

이렇게 데이터 크기도 크고 중요한 Big Transaction Table을 관리하는 부분에서 Troubleshooting이
발생될 경우 데이터베이스의 성능 및 관리작업에 심각한 영향을 받을 수 있다.

이러한 리스크가 있는 Big Transaction Table을 보다 효율적으로 관리하기 위해 Table을
작은 단위로 나눔으로써 데이터 액세스 작업의 성능 향상을 유도하고 데이터 관리를 보다
수월하게 하고자 하는 개념이다.

2. 파티션 테이블의 장점
1) 개선된 가용성
- 파티션은 독립적으로 관리된다.
- Backup and Restore를 파티션별로 작업할 수 있다.
- 같은 테이블에서 Unavailable한 파티션은 다른 파티션에 영향을 주지 않는다.
2) 관리의 용이성
- 사용자가 지정한 값으로 파티션이 가능하다.
- 테이블스페이스간에 파티션 이동이 가능하다.
- 파티션 레벨에서 Select, Delete, Update가 가능하다.
3) 개선된 성능
- 데이터를 액세스할 때 액세스하는 범위를 줄여 퍼포먼스 향상을 가져올 수 있다.
- RAC(Real Application Clusters) 환경에서 인스턴스간 Block Contention을 감소시킨다.

3. 파티션 테이블 사용시 주의할 점
1) 관리적인 관점
- 하나의 테이블을 세분화하여 관리하기 때문에 보다 세심한 관리가 요구된다.
- 파티션을 잘 못 구성 또는 관리하여 IU(Index Unusable)에 빠지는 것을 주의해야 한다.
2) 사용하는 관점
- 파티션 키로 나누어져 있는 테이블에 파티션 키를 조건으로 주지 않아 전체 파티션을 액세스하지
않도록 주의해야 한다.

4. 파티션 테이블의 특징
- 파티션 테이블은 파티션 키 값에 의해 구성되며, 한 테이블 당 가능한 파티션은 이론적으로 65,535개를
지원하나 실질적으로는 10,000개까지만 생성 가능하다(Oracle Ver 10.2.0.3 테스트)


- 모든 파티션 테이블(또는 인덱스)는 같은 Logical Attribute를 가져야 한다.
Ex) Columns, Data Types, Constraints...


- 모든 파티션 테이블(또는 인덱스)는 다른 Physical Attribute를 가져야 한다.
Ex) PCTFREE, PCTUSED, INITTRANS, MAXTRANS, TABLESPACE, STORAGE...


- 파티션 테이블은 'KEY', 'VALUES LESS THAN Literal', 'Physical Attributes'로 구성된다.


- 'VALUES LESS THAN Literal' 절에서 'Literal' 값에는 SQL Function을 지원한다.


- Composite Column 구성은 16개까지 가능하다.

II. 파티션 종류

1. Oracle 버전에 따른 파티션
1) Oracle Ver 7.3
- Partition View를 처음으로 도입하였다.
- 당시 Partition View는 큰 테이블을 동일한 템플릿을 가진 여러 개의 다른 테이블로 분할하고
UNION ALL을 사용하여 View로 묶은 형태이다.
- 그러나 이 방식은 관리의 어려움, 활용성의 부족, 성능등에 대한 이슈로 인하여 Oracle Ver 9i에서는
더이상 지원하지 않는다.


2) Oracle Ver 8.0
- 컬럼 값의 Range 기반으로 된 Range Partition이 최초로 도입되었고, 비로서 Partition의 모습을 갖추었다.
- 각 파티션은 각기 다른 테이블 스페이스, Segment에 저장이 가능하다.


3) Oracle Ver 8i
- 컬럼 값의 Hash 기반으로 된 hash partition과, Sub Partition을 할 수 있는 Composite Partition이 추가되었다.
- 이 당시 Composite Partition은 Range-Hash로만 구성 가능함.


4) Oracle Ver 9i
- 리스트 값으로 파티션을 할 수 있는 List Partition이 추가되었다.
- Composite Partition에서는 Range-Hash 이외에 Range-List가 추가 지원되었다.


5) Oracle Ver 10g
- IOT 파티션이 추가되었다.


6) Oracle Ver 11g
- Composite Partition에서 확장된 Extended Composite Partition이 지원된다.
-> Range-Range, List-Range, List-Hash, List-List
- Reference Partition 추가
- Interval Partition 추가
- System Partition 추가
- Virtual Column Partition 추가

2. Partition Table
1) Range Partition
- Column Value의 범위를 기준으로 하여 행을 분할하는 형태이다.
- Range Partition에서 Table은 단지 논리적인 구조이며 실제 데이터가 물리적으로 저장되는 곳은
Partition으로 나누어진 Tablespace에 저장이 된다.
- PARTITION BY RANGE ( column_list ) : 기본 Table에서 어느 Column을 기준으로 분할할지를 정함.
VALUES LESS THAN ( value_list ) : 각 Partition이 어떤 값의 범위를 포함 할지 Upper Bound를 정함.
- 구문 Sample
CREATE TABLE SALES_DATA_2008
(
COLUMN_1 NUMBER NOT NULL,
COLUMN_2 VARCHAR2(4),
COLUMN_3 VARCHAR2(4),
COLUMN_4 VARCHAR2(2),
COLUMN_5 VARCHAR2(2),
COLUMN_6 NUMBER
)
TABLESPACE TABLE_SPACE_DATA_1
PCTFREE 5
PCTUSED 40
INITRANS 11
MAXTRANS 255
STORAGE
(
INITIAL 2048K
NEXT 1024K
PCTINCREASE 0
MINEXTENTS 1
MAXEXTENTS 121
)
PARTITION BY RANGE ( COLUMN_3, COLUMN_4, COLUMN_5 )
(
PARTITION P_200801 VALUES LESS THAN ('2008', '04', '01' ),
PARTITION P_200802 VALUES LESS THAN ('2008', '07', '01' ),
PARTITION P_200803 VALUES LESS THAN ('2008', '10', '01' ),
PARTITION P_200804 VALUES LESS THAN ('2009', '01', '01' ),
PARTITION P_5 VALUES LESS THAN (MAXVALUE)
TABLESPACE TABLE_SPACE_DATA_2
PCTFREE 5
PCTUSED 40
INITRANS 11
MAXTRANS 255
STORAGE
(
INITIAL 1M
NEXT 1M
PCTINCREASE 0
MINEXTENTS 1
MAXEXTENTS 121
);

2) Hash Partition
- Partitioning column의 Partitioning Key 값에 Hash 함수를 적용하여 Data를 분할하는 방식.
- 데이터 이력관리의 목적 보다 성능 향상의 목적으로 나온 개념이다.
Hash Partition은 Range Partition에서 범위를 기반으로 나누었을 경우 특정 범위에 분포도가 몰려서
- 각기 Size가 다르게 되는 것을 보완하여, 일정한 분포를 가진 파티션으로 나누고 균등한 데이터 분포도를
이용한 병렬처리로 퍼포먼스를 보다 향상시킬 수 있다.
- Hash Partition에서 Table은 단지 논리적인 구조이며 실제 데이터가 물리적으로 저장되는 곳은
Partition으로 나누어진 Tablespace에 저장이 된다.
- 구문 Sample
CREATE TABLE SALES_DATA_2008
(
COLUMN_1 NUMBER NOT NULL,
COLUMN_2 VARCHAR2(4),
COLUMN_3 VARCHAR2(4),
COLUMN_4 VARCHAR2(2),
COLUMN_5 VARCHAR2(2),
COLUMN_6 NUMBER
)
TABLESPACE TABLE_SPACE_DATA_1
PCTFREE 5
PCTUSED 40
INITRANS 11
MAXTRANS 255
STORAGE
(
INITIAL 2048K
NEXT 1024K
PCTINCREASE 0
MINEXTENTS 1
MAXEXTENTS 121
)
PARTITION BY HASH ( COLUMN_3, COLUMN_4, COLUMN_5 )
(
PARTITION P_200801,
PARTITION P_200802,
PARTITION P_200803,
PARTITION P_200804,
PARTITION P_5 VALUES LESS THAN (MAXVALUE)
)
);

3) Composite(Sub) Partition
- 파티션의 컬럼을 Main-Sub 관계로 나누어 분할하는 방식.
- Composite Partition이 아닌 다른 파티션에서 물리적인 데이터가 저장되는 곳은 Table이 아닌
Partition Table에 저장이 되는 것처럼, Composite Partition에서는 Main Partition이 아닌
Sub Partition에 저장된다.
- Composite Partition의 조합 구성은 Oracle의 버전이 올라갈수록 조합하는 방식을 다양하게 지원한다.




- 구문 Sample
CREATE TABLE SALES_DATA_2008
(
COLUMN_1 NUMBER NOT NULL,
COLUMN_2 VARCHAR2(4),
COLUMN_3 VARCHAR2(4),
COLUMN_4 VARCHAR2(2),
COLUMN_5 VARCHAR2(2),
COLUMN_6 NUMBER
)
TABLESPACE TABLE_SPACE_DATA_1
PCTFREE 5
PCTUSED 40
INITRANS 11
MAXTRANS 255
STORAGE
(
INITIAL 2048K
NEXT 1024K
PCTINCREASE 0
MINEXTENTS 1
MAXEXTENTS 121
)
PARTITION BY RANGE ( COLUMN_3, COLUMN_4 )
SUBPARTITION BY HASH ( COLUMN_5 )
(PARTITION P_200801 VALUES LESS THAN ('2008', '04'),
PARTITION P_200802 VALUES LESS THAN ('2008', '07'),
PARTITION P_200803 VALUES LESS THAN ('2008', '10')
(SUBPARTITIONS P_200803_S1 TABLESPACE TABLE_SPACE_DATA_1_1,
SUBPARTITIONS P_200803_S2 TABLESPACE TABLE_SPACE_DATA_1_2,
SUBPARTITIONS P_200803_S3 TABLESPACE TABLE_SPACE_DATA_1_3,
SUBPARTITIONS P_200803_S4 TABLESPACE TABLE_SPACE_DATA_1_4,
SUBPARTITIONS P_200803_S5 TABLESPACE TABLE_SPACE_DATA_1_5,
SUBPARTITIONS P_200803_S6 TABLESPACE TABLE_SPACE_DATA_1_6,
SUBPARTITIONS P_200803_S7 TABLESPACE TABLE_SPACE_DATA_1_7,
SUBPARTITIONS P_200803_S8 TABLESPACE TABLE_SPACE_DATA_1_8
),
PARTITION P_200804 VALUES LESS THAN ('2009', '01')
);

4) List Partition
- Partitioning column의 특정 값으로 분할하는 방식
- 데이터 분포도가 낮지 않고, 균등하게 분포되어 있을 때 유용하다.
- Composite Partition에서 'Range-List'일 경우 그 효율이 더욱 높아진다.
- 다른 파티션 방식처럼 다중 컬럼을 지원하지 않고 단일 컬럼만 가능하다.
- 구문 Sample
CREATE TABLE SALES_DATA_2008
(
COLUMN_1 NUMBER NOT NULL,
COLUMN_2 VARCHAR2(4),
COLUMN_3 VARCHAR2(4),
COLUMN_4 VARCHAR2(2),
COLUMN_5 VARCHAR2(2),
COLUMN_6 NUMBER
)
TABLESPACE TABLE_SPACE_DATA_1
PCTFREE 5
PCTUSED 40
INITRANS 11
MAXTRANS 255
STORAGE
(
INITIAL 2048K
NEXT 1024K
PCTINCREASE 0
MINEXTENTS 1
MAXEXTENTS 121
)
PARTITION BY LIST(COLUMN_2)
(
PARTITION RS VALUES('A') TABLESPACE TABLE_SPACE_DATA_2,
PARTITION RM VALUES('B') TABLESPACE TABLE_SPACE_DATA_3,
PARTITION RN VALUES('C') TABLESPACE TABLE_SPACE_DATA_4,
);

5) Reference Partition
- Reference Key로 지정된 경우 부모 테이블의 컬럼이 존재하지 않아도 부모의 Partition Key로
분할하는 방식.
- 구문 Sample
CREATE TABLE CUSTOMERS
(
CUST_ID NUMBER PRIMARY KEY,
CUST_NAME VARCHAR2(200),
RATING VARCHAR2(1) NOT NULL
)
PARTITION BY LIST(RATING)
(
PARTITION PA VALUES('A'),
PARTITION PB VALUES('B')
);

-- Detail Table
CREATE TABLE SALES
(
SALES_ID NUMBER PRIMARY KEY,
CUST_ID NUMBER NOT NULL,
SALES_AMT NUMBER,
CONSTRAINT FK_SALES_01 FOREIGN KEY (CUST_ID) REFERENCES CUSTOMERS
)
PARTITION BY REFERENCE (FK_SALES_01);
- 제약조건
-> Foreign Key 제약조건이 설정되어 있어야 한다.
-> 상속받는 테이블의 Key값이 NOT NULL 이어야 한다.
- 테스트
-- Normal
SELECT *
FROM SALE_TMP A,
CUSTOMERS B
WHERE A.CUST_ID = B.CUST_ID
AND B.RATING = 'A';

Rows Row Source Operation
------- ------------------------------------
0 STATEMENT
28 HASH JOIN
28 PARTITION LIST SINGLE PARTITION: 1
28 TABLE ACCESS FULL CUSTOMERS PARTITION: 1
56 TABLE ACCESS FULL SALE_TMP

-- Reference Partition
SELECT *
FROM SALES A,
CUSTOMERS B
WHERE A.CUST_ID = B.CUST_ID
AND B.RATING = 'A';

Rows Row Source Operation
------- -------------------------------------
0 STATEMENT
28 PARTITION LIST SINGLE PARTITION: 1
28 HASH JOIN
28 TABLE ACCESS FULL CUSTOMERS PARTITION: 1
28 TABLE ACCESS FULL SALES PARTITION: 1

6) Interval Partition
- Range Partition에서 특정 범위를 지정하고 관리할때는 미리 Range를 만들어주어야 하고
생성 이후 분할 또는 병합을 할 때는 추가적인 작업을 해주어야 한다.
- 하지만 'Interval Partition'에서는 각 파티션을 미리 정의함으로써 파티션 생성을 오라클이
직업 해주는 방식이다.
- 예제 Sample
-- 1. Range Partition 생성
CREATE TABLE SALES6
(
SALES_ID NUMBER,
SALES_DT DATE
)
PARTITION BY RANGE(SALES_DT)
(
PARTITION P0701 VALUES LESS THAN (TO_DATE('20070201', 'YYYYMMDD')),
PARTITION P0701 VALUES LESS THAN (TO_DATE('20070301', 'YYYYMMDD'))
);

-- 2. Partition Key 값의 범위에 없는 값으로 Insert
INSERT INTO SALES6 VALUES(1, TO_DATE('20070401', 'YYYYMMDD'));

-- Error
ORA-14400: inserted partition key does not map to any PARTITION

-- 3. Interval Partition 생성
CREATE TABLE SALES6
(
SALES_ID NUMBER,
SALES_DT DATE
)
PARTITION BY RANGE(SALES_DT) INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'))
(
PARTITION P0701 VALUES LESS THAN(TO_DATE('20080201', 'YYYYMMDD'))
);

-- 4. Partition Key 값의 범위에 없는 값으로 Insert
INSERT INTO SALES6 VALUES(1, TO_DATE('20070601', 'YYYYMMDD'));

-- No Error
1 row created.

- 파티션을 특정 테이블 스페이스에 저장하고 싶다면 STORE IN 구문으로 가능하다.
-> INTERVAL (NUMTOYMINTERVAL(1, 'MONTH')) STORE IN (TS1, TS2, TS3)
- 어플리케이션 개발자가 특정 파티션에 접근하고 싶다면 다음의 구문으로 가능하다.
-> SELECT * FROM SALES6 PARTITION FOR(TO_DATE('20080501', 'YYYYMMDD'));

7) System Partition
- 테이블 생성시 파티션 구간을 미리 설정하는 것이 아니라 임의로 나눈 파티션에 대해
사용자가 원하는 파티션에 데이터를 저장하는 방식.
- 이 방식은 사용자가 'System Partition'으로 되어 있는 테이블의 데이터를 DML 하고자 할 때
직접 파티션을 지정하여 해주어야 한다.
- 로컬 인덱스 생성 시, 인덱스도 동일한 방법으로 파티셔닝된다.
- 예제 Sample
CREATE TABLE SALES3
(
SALES_ID NUMBER,
PRODUCT_CODE NUMBER,
STATE_CODE NUMBER
)
PARTITION BY SYSTEM
(
PARTITION P1 TABLESPACE USERS,
PARTITION P2 TABLESPACE USERS
);
- Insert 할 때는 반드시 파티션을 지정해 주어야 한다.
-- Insert 할 때 테이블의 파티션을 지정하지 않을 경우
INSERT INTO SALES3 VALUES(1,101,1);

-- Error
ERROR at line 1:
ORA-14701: partition-extended name or bind variable must be used for DMLs on
tables partitioned by the System method

-- Insert을 할 때 테이블의 파티션을 지정한 경우
insert into sales3 partition (p1) values (1,101,1);

-- No Error
1 row created.
- Delete, Update 할 때는 필수는 아니지만 파티션을 지정하지 않을 경우 모든 파티션을
찾아다녀야 하므로 이 경우에도 가급적 파티션을 지정해 주어야 한다.
-> DELETE SALES3 PARTITION(P1) WHERE STATUS_CODE = 1;

8) Virtual Column Partition
- 파티션으로 나누고자 하는 컬럼이 테이블에서 가공되어 얻을 수 있는 컬럼일 경우
11g 이전에서는 새로운 컬럼을 추가하고 트리거를 이용하여 컬럼 값을 생성하는 방법을
사용하여 많은 오버헤드를 감수하였으나, 11g에서는 'Virtual Column Partition'을
지원하여 실제로 저장되지 않는 컬럼을 런타임에 계산하여 생성할 수 있다. 또한
가상 컬럼에 파티션을 적용하는 것도 가능하다.
- 예제 Sample
-- Virtual Partition 생성
CREATE TABLE SALES
(
SALES_ID NUMBER,
CUST_ID NUMBER,
SALE_CATEGORY VARCHAR2(6)
GENERATED ALWAYS AS
(
CASE WHEN SALES_AMT <= 10000 THEN 'LOW'
WHEN SALES_AMT BETWEEN 10000 AND 100000 THEN CASE WHEN CUST_ID < 101 THEN 'LOW'
WHEN BETWEEN 101 AND 200 THEN 'MEDIUM'
ELSE 'LOW' END
WHEN SALES_AMT BETWEEN 100000 AND 1000000 THEN CASE WHEN CUST_ID < 101 THEN 'MEDIUM'
WHEN BETWEEN 101 AND 200 THEN 'HIGH'
ELSE 'ULTRA' END
ELSE 'ULTRA' END
) VIRTUAL
)
PARTITION BY LIST(SALES_CATEGORY)
(
PARTITION P_LOW VALUES ('LOW'),
PARTITION P_MEDIUM VALUES ('MEDIUM'),
PARTITION P_HIGH VALUES ('HIGH'),
PARTITION P_ULTRA VALUES ('ULTRA')
);

-- Insert 테스트
INSERT INTO SALES(SALES_ID, CUST_ID, SALES_AMT) VALUES(1, 1, 100);

-- No Error
1 row created.

3. Partition Index
1) Local Index
- 인덱스를 생성한 인덱스와 파티션된 인덱스가 동일하게 파티션된 형태를 말한다.
- 인덱스와 테이블은 같은 칼럼에 의해 파티션되며, 하나의 인덱스 파티션이 테이블
파티션 하나와 대응되며, 대응되는 인덱스 파티션과 테이블 파티션은 각각 같은 범위를 갖게 된다.
- 결국 특정한 하나의 인덱스에 포함된 모든 Key들은 하나의 테이블 파티션 내의 데이타만을 가리키게 된다.

1-1) Local Prefixed Index
- 인덱스의 맨 앞에 있는 컬럼에 의해 파티션되는 방식이다.
- Local Prefixed Index에서 컬럼은 Unique/Non-Unique를 모두 허용한다.
- Base Table의 파티션이 변경되면 Local Index의 관련 파티션만 변경이 된다.
CREATE TABLE DEPT
(
DEPTNO NUMBER NOT NULL,
DNAME VARCHAR2(10) NOT NULL,
LOC VARCHAR2(14)
)
PARTITION BY RANGE (DEPTNO)
(PARTITION PART_1 VALUES LESS THAN (30),
PARTITION PART_2 VALUES LESS THAN (MAXVALUE)
);

CREATE INDEX DEPT_N1 ON DEPT(DEPTNO) LOCAL;

1-2) Local Non-Prefixed Index
- Index의 첫번째 column이 Partition Key가 아닌 형태로 Base Table과 동일한 Partition구조를 가진 Index이다.
(equi-partitioned)
- 빠른 access가 요구될 때 유용하다(Base Table의 Partition Key 는 제외...)
- Partition단위로 관리할 수 있으므로 Global Index에 비해 운영상 편리하다.
- OLAP 측면에서 Global Index보다 조회 속도가 저하된다.
CREATE TABLE DEPT
(
DEPTNO NUMBER NOT NULL,
DNAME VARCHAR2(10) NOT NULL,
LOC VARCHAR2(14)
)
PARTITION BY RANGE (DEPTNO)
(PARTITION PART_1 VALUES LESS THAN (30),
PARTITION PART_2 VALUES LESS THAN (MAXVALUE)
);

CREATE INDEX DEPT_N2 ON DEPT(LOC) LOCAL;

2) Global Index
- Global Index는 테이블과 다르게 파티션되는 경우이다.

2-1) Global Prefixed Index
- Base Table과 비교하여 not equi-partitioned 상태이다.
- Oracle은 only Index structure만 관리한다 (Partition은 관리안함)
- 최종 Partition에는 Maxvalue값이 반드시 기술되어야 한다.
- Local index보다 관리하기 힘들다.
- 기준 Table의 Partition이 변경되면 global index의 모든 Partition에 영향을 미친다
(Global Index 재생성 해야 함) -- 테이블 생성
CREATE TABLE SALES_DATA_2008
(
COLUMN_1 NUMBER NOT NULL,
COLUMN_2 VARCHAR2(4),
COLUMN_3 VARCHAR2(4),
COLUMN_4 VARCHAR2(2),
COLUMN_5 VARCHAR2(2),
COLUMN_6 NUMBER
)
PARTITION BY RANGE ( COLUMN_3, COLUMN_4 )
(
PARTITION P_200801 VALUES LESS THAN ( '04', '01' ),
PARTITION P_200802 VALUES LESS THAN ( '07', '01' ),
PARTITION P_200803 VALUES LESS THAN ( '10', '01' ),
PARTITION P_200804 VALUES LESS THAN ( '12', MAXVALUE )
);

-- Global Prefixed Index
CREATE UNIQUE INDEX RANGE2_GPX8 ON SALES_DATA_2008( COLUMN_2, COLUMN_1)
TABLESPACE TABLE_SPACE_DATA_1
PCTFREE 10
STORAGE(INITIAL 100K NEXT 100K PCTINCREASE 0 )
GLOBAL PARTITION BY RANGE ( CODE )
(
PARTITION P_2008_P1 VALUES LESS THAN ('2000'),
PARTITION P_2008_P2 VALUES LESS THAN ('3000'),
PARTITION P_2008_P3 VALUES LESS THAN (MAXVALUE)
);


2-2) Non-Partitioned Index
- 파티션과는 아무런 상관없는 Normal Index를 말함.


III. 파티션을 사용할 때 알아야 할 사항들

1. 파티션 테이블 및 인덱스 관리를 위한 명령어들
1) 일반 테이블 파티션하기
- Export/Import! 하는 방법
-- 테이블을 Export 한다.
exp user/password tables=number file=exp.dmp

-- 백업받은 테이블을 제거한다.
drop table numbers;

-- 파티션 테이블을 생성한다.
CREATE TABLE NUMBER(QTY NUMBER(3), NAME VARCHAR2(15))
PARTITION BY RANGE(QTY)
(PARTITION P1 VALUES LESS THAN (501),
PARTITION P2 VALUES LESS THAN (MAXVALUE));

-- ignore=y를 사용하여 데이터를 Import!한다.
imp user/password tables=number file=exp.dmp ignore=y

- Subquery를 이용한 방법
-- 파티션 테이블을 생성한다.
CREATE TABLE PARTBL(QTY NUMBER(3), NAME VARCHAR2(15))
PARTITION BY RANGE(QTY)
(PARTITION P1 VALUES LESS THAN(501),
PARTITION P2 VALUES LESS THAN(MAXVALUE));

-- Subquery를 이용하여 파티션 테이블에 데이터를 입력한다.
INSERT INTO PARTBL(QTY, NAME) SELECT * FROM ORIGTBL;

-- Subquery를 이용하여 파티션 테이블에 데이터를 입력한다.

- Partition Exchange 명령어를 사용하는 방법
-- ALTER TABLE EXCHANGE PARTITION은 파티션 테이블을 일반 테이블로, 또는 파티션되어
-- 있지 않은 테이블을 파티션 테이블로 변경시킬 때 사용한다.
-- 파티션 테이블 생성
CREATE TABLE P_EMP (SAL NUMBER(7,2))
PARTITION BY RANGE(SAL)
(PARTITION EMP_P1 VALUES LESS THAN (2000),
PARTITION EMP_P2 VALUES LESS THAN (4000));

-- 첫번째 파티션에 들어갈 데이터
CREATE TABLE DUMMY_Y
SELECT SAL
FROM EMP
WHERE SAL < 2000;

-- 두번째 파티션에 들어갈 데이터
CREATE TABLE DUMMY_Z
SELECT SAL
FROM EMP
WHERE SAL BETWEEN 2000 AND 3999;

ALTER TABLE P_EMP EXCHANGE PARTITION EMP_P1
WITH TABLE DUMMY_Y;

ALTER TABLE P_EMP EXCHANGE PARTITION EMP_P2
WITH TABLE DUMMY_Z;

- 여러 개의 파티션으로 분리된 테이블 중 일부의 파티션만 가진 테이블 생성하기
-- 데이타를 Export한 후 필요한 파티션으로 이루어진 테이블을 생성한다.
-- 데이터 생성
CREATE TABLE YEAR(COL1 DATE) PARTITION BY RANGE (COL1)
(PARTITION OCTOBER VALUES LESS THAN ('01-NOV-1999) TABLESPACE OCTOBER,
PARTITION NOVEMBER VALUES LESS THAN ('01-DEC-1999) TABLESPACE NOVEMBER,
PARTITION DECEMBER VALUES LESS THAN (MAXVALUE) TABLESPACE DECEMBER);

-- 데이타를 Import!
IMP USERNAME/PASSWORD FILE=EXPDAT.DMP FROMUSER=<OWNER> TOUSER=<OWNER>
TABLES=(YEAR:OCTOBER, YEAR:NOVEMBER, YEAR:DECEMBER)

- 파티션을 추가하는 방법
-- 파티션 테이블 생성
CREATE TABLE PART_TBL
(IN_DATE CHAR(8) PRIMARY KEY,
EMPNO NUMBER,
ENAME VARCHAR2(20),
JOB VARCHAR2(20))
PARTITION BY RANGE (IN_DATE)
(PARTITION PART_TBL_03 VALUE LESS THAN ('20000331') TABLESPACE PTS_03,
PARTITION PART_TBL_04 VALUE LESS THAN ('20000430') TABLESPACE PTS_04,
PARTITION PART_TBL_05 VALUE LESS THAN ('20000531') TABLESPACE PTS_05,
PARTITION PART_TBL_06 VALUE LESS THAN ('20000630') TABLESPACE PTS_06,
PARTITION PART_TBL_07 VALUE LESS THAN ('20000731') TABLESPACE PTS_07,
PARTITION PART_TBL_08 VALUE LESS THAN ('20000831') TABLESPACE PTS_08,
PARTITION PART_TBL_09 VALUE LESS THAN ('20000930') TABLESPACE PTS_09,
PARTITION PART_TBL_10 VALUE LESS THAN ('20001031') TABLESPACE PTS_10);

-- 파티션 추가
ALTER TABLE PART_TBL ADD PARTITION PART_TBL_11 VALUES LESS THAN ('20001130') TABLESPACE PTS_11;
ALTER TABLE PART_TBL ADD PARTITION PART_TBL_12 VALUES LESS THAN ('20001231') TABLESPACE PTS_12;

- 특정 파티션을 삭제하는 방법
특정 파티션 삭제 이후 삭제한 파티션의 값이 들어올 경우 그 다음 VALUES LESS THAN으로 편입된다.
ALTER TABLE PART_TBL DROP PARTITION PART_TBL_08;

- 파티션을 나누는 방법
만약 3월만 들어가있는 파티션이 있을 경우, 여기서 1, 2월을 추가하려면 파티션에서 Add가 아닌
Split을 해 주어야 한다.
-- 3월 파티션에서 2월과 3월을 Split함.
ALTER TABLE PART_TBL SPLIT PARTITION PART_TBL_03 AT ('20000229')
INTO (PARTITION PART_TBL_02 TABLESPACE PTS_02,
PARTITION PART_TBL_03_1 TABLESPACE PTS_03);

-- 2월 파티션에서 1월과 2월을 Split함.
ALTER TABLE PART_TBL SPLIT PARTITION PART_TBL_02 AT ('20000131')
INTO (PARTITION PART_TBL_01 TABLESPACE PTS_01,
PARTITION PART_TBL_02_1 TABLESPACE PTS_02);

- 파티션 이름을 변경하는 방법
ALTER TABLE PART_TBL RENAME PARTITION PART_TBL_02_1 TO PART_TBL_02;

- 파티션의 테이블스페이스를 옮기는 방법
ALTER TABLE PART_TBL MOVE PARTITION PART_TBL_10 TABLESPACE PTS_10_1 NOLOGGING;

- 특정 파티션의 데이터를 Truncate 하는 방법
Partition의 Data를 모두 삭제하려면 Truncate하는 방법을 사용할 수가 있는데,
Truncate는 Rollback이 불가능하며 특정 Partition 전체를 삭제하므로 주의하여 사용하여야 한다.
ALTER TABLE PART_TBL TRUNCATE PARTITION PART_TBL_02;

- 파티션 테이블의 물리적인 속성 변경하는 방법
Partition Table은 특정 Partition의 속성만 변경할 수 있고,
Table의 속성을 변경하여 전체 Partition에 대해 동일한 변경을 할 수 있다.

-- part_tbl의 모든 Partition의 Next 값이 변경
ALTER TABLE PART_TBL STORAGE (NEXT 10M);

part_tbl_05 Partition의 Maxextents 값만 변경
ALTER TABLE PART_TBL MODIFY PARTITION PART_TBL_05 STORAGE (MAXEXTENTS 1000);

- 인덱스 관리
파티션 테이블 관련 변경작업을 한 후에는 테이블에 걸려있는 Local, Glocal Index에 대해
반드시 Rebuild를 해 주어야 한다. -- 특정 파티션의 인덱스 Rebuild
ALTER INDEX IND_PART_TBL REBUILD PARTITION I_PART_TBL_02;

-- 글로벌 인덱스 Rebuild
ALTER INDEX PART_TBL_PK REBUILD;

2. Backup & Recovery
1) Export
- Table-Level Export
기존의 Table Export처럼 Table 전체를 Export하는 경우이다.
이는 Emp Table(Partitioned 또는 Non-Partitioned) 전체를 Export하는 경우이다.
$ exp scott/tiger tables=emp file=emp.dmp

- Partition-Level Export
이는 Partition Table의 일부 Partition만을 Export하는 것으로,
Full Mode의 Export시에는 사용하지 못하고, Table단위의 Export시에만 가능하다.
':' 을 이용하여 Partition 이름을 지정하며 이 경우 Emp Table의 px Partition만을 Export
$ exp scott/tiger tables=emp:px file=emp_par.dmp

- 다음과 같이 두 가지 경우를 Level을 혼용하여 사용하는 것도 가능하다.
Sales Table은 전부를, Emp Table에서는 px Partition만을 Export.
$ exp scott/tiger tables=(emp:px, sales) file=both.dmp

2) Import!
- Table-Level Import!
Partitioned 또는 Non-Partitioned Table 전체를 Import!한다.
모든 Import! Mode (full, user, table)에서 사용된다.
emp table(Partitioned 또는 non-Partitioned) 전체를 Import!
$ imp scott/tiger file=wookpark.dmp tables=emp

- Partition-Level Import!
Export Dump File에서 (full, user, table중 어떠한 Mode를 이용하여 Export했건간에)
Partitioned Tabled의 일부 Partition만을 Import!한다.
Table Import! Mode에서만 사용가능하다.


-- emp table의 px Partition만을 Import!.
-- ':'을 이용하여 Partition을 지정
$ imp scott/tiger file=wookpark.dmp tables=emp:px

테이블 단위의 Import!시 우선 Table Creation 문장을 수행하고 Row Insert문을 수행하는 것과
마찬가지로, Partition-level Import!도 우선 Partitioned Table의 생성 문장을 수행하고
Row Insert문을 수행하게 된다.
따라서 ignore=y option등을 적절히 사용하면, Non-Partitioned Table과 Partitioned Table간의 변경,
Partitioned Table의 구조 변경등을 수행할 수 있게 된다.
다음에는 그 중 몇 가지 예이다.

1. 파티션되어 있지 않은 테이블을 Exp, Imp를 이용하여 파티션 하는 예

1) 파티션되어 있지 않은 테이블을 Export한다.
$ exp scott/tiger file=wookpark.dmp tables=emp

2) 해당 Table을 Drop한다.
DROP TABLE EMP

3) 파티션 테이블을 생성한다.
CREATE TABLE EMP
(EMPNO NUMBER(4) NOT NULL,
....
)
PARTITION BY RANGE (EMPNO),
(PARTITION EMP1 VALUES LESS THAN (1000) TABLESPACE TS1,
PARTITION EMP1 VALUES LESS THAN (2000) TABLESPACE TS2,
PARTITION EMP1 VALUES LESS THAN (3000) TABLESPACE TS3);

4) Import!한다.
$ imp scott/tiger file=wookpark.dmp tables=emp ignore=y

2. Partitioned Table의 Partition들을 exp/imp를 이용하여 Merge하는 예
1) Merge의 대상이 되는 Partition을 Export한다.
$exp scott/tiger file=wookpark.dmp tables=emp:emp2

2) Merge의 대상이 되는 Partition을 'alter table...'문장으로 Drop한다.
ALTER TABLE EMP DROP PARTITION EMP2;

3) Import!한다.
$imp scott/tiger file=wookpark.dmp tables=emp:emp3 ignore=y
이후 emp Table을 확인하면, emp2 Partition에 있던 Data가 emp3 Partition에 Merge되어 있음을
확인할 수 있다.

3. IU(Index Unusable) 발생 주의
1) IU(Index Unusable)란 파티션이 변경됨으로 인해 파티션 테이블에 있는 인덱스에 영향을 주어
SELECT나 DML을 시도할 때 오류가 발생되는 것을 말한다.

2) IU(Index Unusable)를 발생시키는 Case
- Direct path Load의 경우
Direct path SQL*Loader 수행 후 인덱스가 테이블의 해당 데이터보다 이전 것이면,
Unusable 상태가 된다 (Oracle7에서는 인덱스가 Direct Load State가 되었다고 표현한다).
인덱스가 테이블의 데이터보다 이전 상태라는 것은 데이터를 Load한 후 인덱스를 생성하는 중에
Space 부족 등의 원인으로 오류가 발생하였거나, SKIP_INDEX_MAINTENANCE Option을 사용한 경우이다.

- ROWID가 변경되는 경우
ALTER TABLE MOVE PARTITION과 같이 ROWID를 변화시키는 작업은 영향받는 Local Index와
전체 Global Index를 Unusable 상태가 되게 한다.

- ROWID를 지우는 작업
ALTER TABLE TRUNCATE PARTITION이나 DROP PARTITION과 같이 테이블의 Row를 지우는 경우
영향받는 Local Index Partition과 모든 Global Index Partition을 Unusable 상태로 만든다.

- 테이블 Partition 정의를 변경하는 경우
ALTER TABLE SPLIT PARTITION은 Local Index의 Partition Definition은 변경시키지만,
자동으로 인덱스를 새로운 Definition에 맞게 Rebuild하지 않기 때문에 영향받는
Local Index Partition을 Unusable 상태로 만든다.
또한 이것은 ROWID를 변경시키기 때문에 모든 Global Index Partition을 Unusable 상태로 만든다.

- 인덱스 Partition 정의를 변경하는 경우
ALTER INDEX SPLIT PARTITION은 Index의 Definition은 변경시키지만,
영향받은 Partition은 Rebuild시키지 않는다.
이 작업은 영향받는 인덱스 파티션 부분을 Unusable 상태로 만든다.
그러나 Global Index의 경우는 그대로 Usable 상태로 된다.

3) 결과적으로 IU 상태가 되면 다음과 같이 조치해야 한다.
- Partition Index : Rebuild
- Non-Partition Index : Drop and Recreate

IV. 일반 테이블과 파티션 테이블 테스트
0. 기초 데이터 만들기
1) 일반 테이블

① 테이블
CREATE TABLE APPS.NORMAL_TEST_TAB
(
MON_P1 DATE,
GRP_P2 NUMBER,
CNT_N1 NUMBER
);

② 샘플 데이터 넣기
INSERT INTO APPS.NORMAL_TEST_TAB
SELECT ADD_MONTHS(TO_DATE('200001', 'YYYYMM'),
DECODE(MOD(LEVEL, 10000),
0,
TRUNC(LEVEL / 10000),
TRUNC(LEVEL / 10000) + 1) - 1) MON_P1,
DECODE(MOD(LEVEL, 100),
0,
TRUNC(LEVEL / 100),
TRUNC(LEVEL / 100) + 1) * 100 GRP_P2,
LEVEL CNT_N1
FROM DUAL
CONNECT BY LEVEL <= 1000000
;

COMMIT;

③ 통계정보
BEGIN
DBMS_STATS.GATHER_TABLE_STATS('APPS',
'NORMAL_TEST_TAB',
CASCADE => TRUE);
END;
/

NORMAL_TEST_TAB
---------------
Rows=997,141 Blocks=3,032
Empty Blocks=0 Avg Space=0
Chain Count=0 Avg Row Length=16
Avg Space Freelist Blocks=0 Freelist Blocks=0
Sample Size=54,167 Last Analyze=2008/08/24
Partitioned=NO

Column Name Nullable Column Type Distinct Buckets
-------------------------------- -------- ------------- ---------- ----------
MON_P1 DATE 101 1
GRP_P2 NUMBER 9,999 1
CNT_N1 NUMBER 997,141 1

INDEX
-----------------------------------------------------------------------------

2) 파티션 테이블

① 테이블
CREATE TABLE APPS.PARTITION_TEST_TAB
(
MON_P1 DATE,
GRP_P2 NUMBER,
CNT_N1 NUMBER
)
PARTITION BY RANGE ( MON_P1 )
SUBPARTITION BY HASH( GRP_P2 )
(
PARTITION P200001 VALUES LESS THAN(TO_DATE('200001', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200002 VALUES LESS THAN(TO_DATE('200002', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200003 VALUES LESS THAN(TO_DATE('200003', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200004 VALUES LESS THAN(TO_DATE('200004', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200005 VALUES LESS THAN(TO_DATE('200005', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200006 VALUES LESS THAN(TO_DATE('200006', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200007 VALUES LESS THAN(TO_DATE('200007', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200008 VALUES LESS THAN(TO_DATE('200008', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200009 VALUES LESS THAN(TO_DATE('200009', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200010 VALUES LESS THAN(TO_DATE('200010', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200011 VALUES LESS THAN(TO_DATE('200011', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200012 VALUES LESS THAN(TO_DATE('200012', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200101 VALUES LESS THAN(TO_DATE('200101', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200102 VALUES LESS THAN(TO_DATE('200102', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200103 VALUES LESS THAN(TO_DATE('200103', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200104 VALUES LESS THAN(TO_DATE('200104', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200105 VALUES LESS THAN(TO_DATE('200105', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200106 VALUES LESS THAN(TO_DATE('200106', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200107 VALUES LESS THAN(TO_DATE('200107', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200108 VALUES LESS THAN(TO_DATE('200108', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200109 VALUES LESS THAN(TO_DATE('200109', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200110 VALUES LESS THAN(TO_DATE('200110', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200111 VALUES LESS THAN(TO_DATE('200111', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200112 VALUES LESS THAN(TO_DATE('200112', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200201 VALUES LESS THAN(TO_DATE('200201', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200202 VALUES LESS THAN(TO_DATE('200202', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200203 VALUES LESS THAN(TO_DATE('200203', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200204 VALUES LESS THAN(TO_DATE('200204', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200205 VALUES LESS THAN(TO_DATE('200205', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200206 VALUES LESS THAN(TO_DATE('200206', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200207 VALUES LESS THAN(TO_DATE('200207', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200208 VALUES LESS THAN(TO_DATE('200208', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200209 VALUES LESS THAN(TO_DATE('200209', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200210 VALUES LESS THAN(TO_DATE('200210', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200211 VALUES LESS THAN(TO_DATE('200211', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200212 VALUES LESS THAN(TO_DATE('200212', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200301 VALUES LESS THAN(TO_DATE('200301', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200302 VALUES LESS THAN(TO_DATE('200302', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200303 VALUES LESS THAN(TO_DATE('200303', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200304 VALUES LESS THAN(TO_DATE('200304', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200305 VALUES LESS THAN(TO_DATE('200305', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200306 VALUES LESS THAN(TO_DATE('200306', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200307 VALUES LESS THAN(TO_DATE('200307', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200308 VALUES LESS THAN(TO_DATE('200308', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200309 VALUES LESS THAN(TO_DATE('200309', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200310 VALUES LESS THAN(TO_DATE('200310', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200311 VALUES LESS THAN(TO_DATE('200311', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200312 VALUES LESS THAN(TO_DATE('200312', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200401 VALUES LESS THAN(TO_DATE('200401', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200402 VALUES LESS THAN(TO_DATE('200402', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200403 VALUES LESS THAN(TO_DATE('200403', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200404 VALUES LESS THAN(TO_DATE('200404', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200405 VALUES LESS THAN(TO_DATE('200405', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200406 VALUES LESS THAN(TO_DATE('200406', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200407 VALUES LESS THAN(TO_DATE('200407', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200408 VALUES LESS THAN(TO_DATE('200408', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200409 VALUES LESS THAN(TO_DATE('200409', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200410 VALUES LESS THAN(TO_DATE('200410', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200411 VALUES LESS THAN(TO_DATE('200411', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200412 VALUES LESS THAN(TO_DATE('200412', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200501 VALUES LESS THAN(TO_DATE('200501', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200502 VALUES LESS THAN(TO_DATE('200502', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200503 VALUES LESS THAN(TO_DATE('200503', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200504 VALUES LESS THAN(TO_DATE('200504', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200505 VALUES LESS THAN(TO_DATE('200505', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200506 VALUES LESS THAN(TO_DATE('200506', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200507 VALUES LESS THAN(TO_DATE('200507', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200508 VALUES LESS THAN(TO_DATE('200508', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200509 VALUES LESS THAN(TO_DATE('200509', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200510 VALUES LESS THAN(TO_DATE('200510', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200511 VALUES LESS THAN(TO_DATE('200511', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200512 VALUES LESS THAN(TO_DATE('200512', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200601 VALUES LESS THAN(TO_DATE('200601', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200602 VALUES LESS THAN(TO_DATE('200602', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200603 VALUES LESS THAN(TO_DATE('200603', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200604 VALUES LESS THAN(TO_DATE('200604', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200605 VALUES LESS THAN(TO_DATE('200605', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200606 VALUES LESS THAN(TO_DATE('200606', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200607 VALUES LESS THAN(TO_DATE('200607', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200608 VALUES LESS THAN(TO_DATE('200608', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200609 VALUES LESS THAN(TO_DATE('200609', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200610 VALUES LESS THAN(TO_DATE('200610', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200611 VALUES LESS THAN(TO_DATE('200611', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200612 VALUES LESS THAN(TO_DATE('200612', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200701 VALUES LESS THAN(TO_DATE('200701', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200702 VALUES LESS THAN(TO_DATE('200702', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200703 VALUES LESS THAN(TO_DATE('200703', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200704 VALUES LESS THAN(TO_DATE('200704', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200705 VALUES LESS THAN(TO_DATE('200705', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200706 VALUES LESS THAN(TO_DATE('200706', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200707 VALUES LESS THAN(TO_DATE('200707', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200708 VALUES LESS THAN(TO_DATE('200708', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200709 VALUES LESS THAN(TO_DATE('200709', 'YYYYMM')) SUBPARTITIONS 100,
-- 9400에서 10,000개 파티션에 근접해서 더 늘어나는 구간이라 MAXVALUE 처리함
PARTITION P5 VALUES LESS THAN(MAXVALUE) SUBPARTITIONS 100
);

② 샘플 데이터 넣기
INSERT INTO APPS.PARTITION_TEST_TAB
SELECT ADD_MONTHS(TO_DATE('200001', 'YYYYMM'),
DECODE(MOD(LEVEL, 10000),
0,
TRUNC(LEVEL / 10000),
TRUNC(LEVEL / 10000) + 1) - 1) MON_P1,
DECODE(MOD(LEVEL, 100),
0,
TRUNC(LEVEL / 100),
TRUNC(LEVEL / 100) + 1) * 100 GRP_P2,
LEVEL CNT_N1
FROM DUAL
CONNECT BY LEVEL <= 1000000
;

COMMIT;

③ 통계정보
BEGIN
DBMS_STATS.GATHER_TABLE_STATS('APPS',
'PARTITION_TEST_TAB',
CASCADE => TRUE);
END;
/

PARTITION_TEST_TAB
------------------
Rows=998,668 Blocks=74,646
Empty Blocks=0 Avg Space=0
Chain Count=0 Avg Row Length=16
Avg Space Freelist Blocks=0 Freelist Blocks=0
Sample Size=56,777 Last Analyze=2008/08/24
Partitioned=YES

Column Name Nullable Column Type Distinct Buckets
-------------------------------- -------- ------------- ---------- ----------
MON_P1 DATE 101 1
GRP_P2 NUMBER 9,994 1
CNT_N1 NUMBER 998,668 1

INDEX
-----------------------------------------------------------------------------


1. Full Table Scan
1) 파티션 키로 Full Table Scan

① 일반 테이블
SELECT *
FROM NORMAL_TEST_TAB
WHERE MON_P1 = :B1 -- 2007/01/01
AND GRP_P2 = :B2 -- 841000
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 11 0.080 0.087 0 3064 0 100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 13 0.080 0.088 0 3064 0 100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
100 TABLE ACCESS FULL NORMAL_TEST_TAB (cr=3064 pr=0 pw=0 time=70247 us)

② 파티션 테이블
SELECT *
FROM PARTITION_TEST_TAB
WHERE MON_P1 = :B1 -- 2007/01/01
AND GRP_P2 = :B2 -- 841000
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 11 0.000 0.001 0 25 0 100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 13 0.000 0.001 0 25 0 100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
100 PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=25 pr=0 pw=0 time=120 us)
100 PARTITION HASH SINGLE PARTITION: KEY KEY (cr=25 pr=0 pw=0 time=96 us)
100 TABLE ACCESS FULL PARTITION_TEST_TAB PARTITION: KEY KEY (cr=25 pr=0 pw=0 time=80 us)


2) 파티션 키가 아닌 것으로 Full Table Scan

① 일반 테이블
SELECT *
FROM NORMAL_TEST_TAB
WHERE CNT_N1 = :B1 -- 900000
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 2 0.400 0.412 0 3055 0 1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 4 0.400 0.412 0 3055 0 1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
1 TABLE ACCESS FULL NORMAL_TEST_TAB (cr=3055 pr=0 pw=0 time=371933 us)

② 파티션 테이블
-- 2개 파티션 키 모두 없이
SELECT *
FROM PARTITION_TEST_TAB
WHERE CNT_N1 = :B1 -- 900000
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 2 0.940 0.936 0 97104 0 1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 4 0.940 0.937 0 97104 0 1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
1 PARTITION RANGE ALL PARTITION: 1 94 (cr=97104 pr=0 pw=0 time=873415 us)
1 PARTITION HASH ALL PARTITION: 1 100 (cr=97104 pr=0 pw=0 time=933492 us)
1 TABLE ACCESS FULL PARTITION_TEST_TAB PARTITION: 1 9400 (cr=97104 pr=0 pw=0 time=924367 us)

-- 1개 파티션 키 선두(1블럭당 5개 로우 액세스 - 그나마 효율)
SELECT *
FROM PARTITION_TEST_TAB
WHERE MON_P1 = :B1 -- 2007/01/01
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 1001 0.000 0.046 0 1948 0 10000
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 1003 0.000 0.046 0 1948 0 10000

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
10000 PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=1948 pr=0 pw=0 time=40165 us)
10000 PARTITION HASH ALL PARTITION: 1 100 (cr=1948 pr=0 pw=0 time=40148 us)
10000 TABLE ACCESS FULL PARTITION_TEST_TAB PARTITION: KEY KEY (cr=1948 pr=0 pw=0 time=3704 us)

-- 1개 파티션 키 후발(100블럭당 8개 로우 액세스 - 비효율적)
SELECT *
FROM PARTITION_TEST_TAB
WHERE GRP_P2 = :B2 -- 841000
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 11 0.010 0.013 0 1240 0 100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 13 0.010 0.013 0 1240 0 100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
100 PARTITION RANGE ALL PARTITION: 1 94 (cr=1240 pr=0 pw=0 time=10802 us)
100 PARTITION HASH SINGLE PARTITION: KEY KEY (cr=1240 pr=0 pw=0 time=12343 us)
100 TABLE ACCESS FULL PARTITION_TEST_TAB PARTITION: (cr=1240 pr=0 pw=0 time=11913 us)

-- 파티션 키에서 선두 없이 후발만 들어오게 되면 비효율적

2. Index Ragne Scan
1) 인덱스 생성

① 일반 테이블
CREATE INDEX APPS.NORMAL_TEST_TAB_N1 ON APPS.NORMAL_TEST_TAB (MON_P1)
TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6;
CREATE INDEX APPS.NORMAL_TEST_TAB_N2 ON APPS.NORMAL_TEST_TAB (MON_P1, GRP_P2)
TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6;
CREATE INDEX APPS.NORMAL_TEST_TAB_N3 ON APPS.NORMAL_TEST_TAB (CNT_N1)
TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6;

ALTER INDEX APPS.NORMAL_TEST_TAB_N1 NOPARALLEL;
ALTER INDEX APPS.NORMAL_TEST_TAB_N2 NOPARALLEL;
ALTER INDEX APPS.NORMAL_TEST_TAB_N3 NOPARALLEL;

② 파티션 테이블
-- Local Prefixed Index
CREATE INDEX APPS.PARTITION_TEST_TAB_N1 ON APPS.PARTITION_TEST_TAB (MON_P1)
TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6 LOCAL;
CREATE INDEX APPS.PARTITION_TEST_TAB_N2 ON APPS.PARTITION_TEST_TAB (MON_P1, GRP_P2)
TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6 LOCAL;

-- Global Prefixed Index
CREATE INDEX APPS.PARTITION_TEST_TAB_N3 ON APPS.PARTITION_TEST_TAB (CNT_N1)
GLOBAL PARTITION BY RANGE(CNT_N1) (PARTITION P1 VALUES LESS THAN (100000),
PARTITION P2 VALUES LESS THAN (200000),
PARTITION P3 VALUES LESS THAN (300000),
PARTITION P4 VALUES LESS THAN (400000),
PARTITION P5 VALUES LESS THAN (500000),
PARTITION P6 VALUES LESS THAN (600000),
PARTITION P7 VALUES LESS THAN (700000),
PARTITION P8 VALUES LESS THAN (800000),
PARTITION P9 VALUES LESS THAN (900000),
PARTITION P10 VALUES LESS THAN (1000000),
PARTITION P11 VALUES LESS THAN (MAXVALUE))
TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6;

ALTER INDEX APPS.PARTITION_TEST_TAB_N1 NOPARALLEL;
ALTER INDEX APPS.PARTITION_TEST_TAB_N2 NOPARALLEL;
ALTER INDEX APPS.PARTITION_TEST_TAB_N3 NOPARALLEL;


3) 통계정보

① 일반 테이블
NORMAL_TEST_TAB
---------------
Rows=997,141 Blocks=3,032
Empty Blocks=0 Avg Space=0
Chain Count=0 Avg Row Length=16
Avg Space Freelist Blocks=0 Freelist Blocks=0
Sample Size=54,167 Last Analyze=2008/08/24
Partitioned=NO

Column Name Nullable Column Type Distinct Buckets
-------------------------------- -------- ------------- ---------- ----------
MON_P1 DATE 101 1
GRP_P2 NUMBER 9,999 1
CNT_N1 NUMBER 997,141 1

INDEX
-----------------------------------------------------------------------------
NORMAL_TEST_TAB_N1 : MON_P1
Type=NORMAL, Uniq=No, Distinct=100, Rows=1,000,000, Last Analyze=2008/08/24
NORMAL_TEST_TAB_N2 : MON_P1 + GRP_P2
Type=NORMAL, Uniq=No, Distinct=10,000, Rows=1,000,000, Last Analyze=2008/08/24
NORMAL_TEST_TAB_N3 : CNT_N1
Type=NORMAL, Uniq=No, Distinct=1,000,000, Rows=1,000,000, Last Analyze=2008/08/24

② 파티션 테이블
PARTITION_TEST_TAB
------------------
Rows=998,668 Blocks=74,646
Empty Blocks=0 Avg Space=0
Chain Count=0 Avg Row Length=16
Avg Space Freelist Blocks=0 Freelist Blocks=0
Sample Size=56,777 Last Analyze=2008/08/24
Partitioned=YES

Column Name Nullable Column Type Distinct Buckets
-------------------------------- -------- ------------- ---------- ----------
MON_P1 DATE 101 1
GRP_P2 NUMBER 9,994 1
CNT_N1 NUMBER 998,668 1

INDEX
-----------------------------------------------------------------------------
PARTITION_TEST_TAB_N1 : MON_P1
Partition=LOCAL NON_PREFIXED
Type=NORMAL, Uniq=No, Distinct=8, Rows=1,000,000, Last Analyze=2008/08/24
PARTITION_TEST_TAB_N2 : MON_P1 + GRP_P2
Partition=LOCAL PREFIXED
Type=NORMAL, Uniq=No, Distinct=10,000, Rows=1,000,000, Last Analyze=2008/08/24
PARTITION_TEST_TAB_N3 : CNT_N1
Partition=GLOBAL PREFIXED
Type=NORMAL, Uniq=No, Distinct=1,000,000, Rows=1,000,000, Last Analyze=2008/08/24


4) 테스트

① 일반 테이블
SELECT *
FROM NORMAL_TEST_TAB
WHERE MON_P1 = :B1 -- 2007/01/01
AND GRP_P2 = :B2 -- 841000
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 11 0.000 0.000 0 24 0 100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 13 0.000 0.001 0 24 0 100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
100 TABLE ACCESS BY INDEX ROWID NORMAL_TEST_TAB (cr=24 pr=0 pw=0 time=36 us)
100 INDEX RANGE SCAN NORMAL_TEST_TAB_N2 (cr=13 pr=0 pw=0 time=621 us)(Object ID 2885525)

SELECT *
FROM NORMAL_TEST_TAB
WHERE CNT_N1 = :B1 -- 900000
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 2 0.000 0.000 0 5 0 1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 4 0.000 0.000 0 5 0 1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
1 TABLE ACCESS BY INDEX ROWID NORMAL_TEST_TAB (cr=5 pr=0 pw=0 time=40 us)
1 INDEX RANGE SCAN NORMAL_TEST_TAB_N3 (cr=4 pr=0 pw=0 time=36 us)(Object ID 2885526)

② 파티션 테이블
SELECT *
FROM PARTITION_TEST_TAB
WHERE MON_P1 = :B1 -- 2007/01/01
AND GRP_P2 = :B2 -- 841000
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 11 0.000 0.001 0 23 0 100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 13 0.000 0.001 0 23 0 100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
100 PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=23 pr=0 pw=0 time=71 us)
100 PARTITION HASH SINGLE PARTITION: KEY KEY (cr=23 pr=0 pw=0 time=55 us)
100 TABLE ACCESS BY LOCAL INDEX ROWID PARTITION_TEST_TAB PARTITION: KEY KEY (cr=23 pr=0 pw=0 time=46 us)
100 INDEX RANGE SCAN PARTITION_TEST_TAB_N2 PARTITION: KEY KEY (cr=12 pr=0 pw=0 time=826 us)(Object ID 2895022)

-- Global Prefixed Index
SELECT *
FROM PARTITION_TEST_TAB
WHERE CNT_N1 = :B1 -- 900000
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 2 0.000 0.000 0 4 0 1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 4 0.000 0.000 0 4 0 1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
1 PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=4 pr=0 pw=0 time=49 us)
1 TABLE ACCESS BY GLOBAL INDEX ROWID PARTITION_TEST_TAB PARTITION: ROW LOCATION ROW LOCATION (cr=4 pr=0 pw=0 time=35 us)
1 INDEX RANGE SCAN PARTITION_TEST_TAB_N3 PARTITION: KEY KEY (cr=3 pr=0 pw=0 time=30 us)(Object ID 2904517)
;

-- Local Non-Prefixed Index
DROP INDEX APPS.PARTITION_TEST_TAB_N3;

CREATE INDEX APPS.PARTITION_TEST_TAB_N3 ON APPS.PARTITION_TEST_TAB (CNT_N1) TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6 LOCAL;

-- FULL COLUMN
SELECT *
FROM PARTITION_TEST_TAB
WHERE MON_P1 = :B1 -- 2007/01/01
AND GRP_P2 = :B2 -- 841000
AND CNT_N1 = :B3 -- 840936
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 2 0.000 0.000 0 4 0 1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 4 0.000 0.000 0 4 0 1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
1 PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=4 pr=0 pw=0 time=99 us)
1 PARTITION HASH SINGLE PARTITION: KEY KEY (cr=4 pr=0 pw=0 time=73 us)
1 TABLE ACCESS BY LOCAL INDEX ROWID PARTITION_TEST_TAB PARTITION: KEY KEY (cr=4 pr=0 pw=0 time=55 us)
1 INDEX RANGE SCAN PARTITION_TEST_TAB_N3 PARTITION: KEY KEY (cr=3 pr=0 pw=0 time=41 us)(Object ID 2904529)

-- 후발 없이(선두키가 없으면 PARALLEL 처리할 떄 보이는 실행계획 나옴)
SELECT *
FROM PARTITION_TEST_TAB
WHERE MON_P1 = :B1 -- 2007/01/01
AND CNT_N1 = :B3 -- 840936
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.018 0 200 0 0
Fetch 2 0.010 0.117 0 0 0 1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 4 0.010 0.135 0 200 0 1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
1 PX COORDINATOR (cr=200 pr=0 pw=0 time=37561 us)
0 PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us)
0 PX PARTITION HASH ALL PARTITION: 1 100 (cr=0 pr=0 pw=0 time=0 us)
0 TABLE ACCESS BY LOCAL INDEX ROWID PARTITION_TEST_TAB PARTITION: KEY KEY (cr=0 pr=0 pw=0 time=0 us)
0 INDEX RANGE SCAN PARTITION_TEST_TAB_N3 PARTITION: KEY KEY (cr=0 pr=0 pw=0 time=0 us)(Object ID 2904529)

-- 선두 없이(선두키가 없으면 PARALLEL 처리할 떄 보이는 실행계획 나옴)
SELECT *
FROM PARTITION_TEST_TAB
WHERE GRP_P2 = :B2 -- 841000
AND CNT_N1 = :B3 -- 840936
;

Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.009 0 188 0 0
Fetch 2 0.010 0.135 0 0 0 1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 4 0.010 0.144 0 188 0 1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
1 PX COORDINATOR (cr=188 pr=0 pw=0 time=46595 us)
0 PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us)
0 PX PARTITION HASH SINGLE PARTITION: KEY KEY (cr=0 pr=0 pw=0 time=0 us)
0 TABLE ACCESS BY LOCAL INDEX ROWID PARTITION_TEST_TAB PARTITION: (cr=0 pr=0 pw=0 time=0 us)
0 INDEX RANGE SCAN PARTITION_TEST_TAB_N3 PARTITION: (cr=0 pr=0 pw=0 time=0 us)(Object ID 2904529)

 

.
Posted by .07274.

댓글을 달아 주세요