강좌

HOME > 강좌 >
강좌| 리눅스 및 오픈소스에 관련된 강좌를 보실 수 있습니다.
 
Merge Table
조회 : 2,796  


Merge Table

 


OS: Microsoft Windows 2000 5.00.2195 Service Pack 3
MySQL: 4.0.7-gamma-nt
CPU: x86 Family 6 Model 8 Stepping 10
RAM: 512MB
작성자: 강명규(kang@dbakorea.pe.kr)

MERGE TABLE은 오라클에서의 union all, 단순 VIEW, PARTITIIONING과 유사한 기능을 제공한다.

여러 테이블의 합이라는 점에서 union all
4.0이하의 버전에서 직접적인 insert를 못하는 점에서는 view
여러개의 데이터파일(테이블은 각각 하나의 데이터파일을 갖는다)을 가진다는 개념에서 파티셔닝.

아래의 예를 보면 알 수 있듯이 HISTORY데이터를 처리하는데 쓰면 유용하다.
몇가지 단점이 있는데 자세한 내용은 스스로 알아보도록 하자.

create table member_2000
(
    id          varchar(15),
    regdate     datetime,
    name        varchar(12),
    KEY member_2000_idx (id)
);

create table member_2001
(
    id          varchar(15),
    regdate     datetime,
    name        varchar(12),
    KEY member_2001_idx (id)
);

create table member_2002
(
    id          varchar(15),
    regdate     datetime,
    name        varchar(12),
    KEY member_2002_idx (id)
);

create table member_2003
(
    id          varchar(15),
    regdate     datetime,
    name        varchar(12),
    KEY member_2003_idx (id)
);

insert into member_2000 values('maddog2000',   '2000-01-01', '강명규2000');
insert into member_2000 values('batman2000',   '2000-01-01', '배트맨2000');
insert into member_2000 values('superman2000', '2000-01-01', '슈퍼맨2000');
insert into member_2001 values('maddog2001',   '2001-01-01', '강명규2001');
insert into member_2001 values('batman2001',   '2001-01-01', '배트맨2001');
insert into member_2001 values('superman2001', '2001-01-01', '슈퍼맨2001');
insert into member_2002 values('maddog2002',   '2002-01-01', '강명규2002');
insert into member_2002 values('batman2002',   '2002-01-01', '배트맨2002');
insert into member_2002 values('superman2002', '2002-01-01', '슈퍼맨2002');
insert into member_2003 values('maddog2003',   '2003-01-01', '강명규2003');
insert into member_2003 values('batman2003',   '2003-01-01', '배트맨2003');
insert into member_2003 values('superman2003', '2003-01-01', '슈퍼맨2003');

CREATE TABLE member_all
(
    id          varchar(15),
    regdate     datetime,
    name        varchar(12),
    KEY member_idx (id)
) TYPE=MERGE UNION=(member_2000,member_2001,member_2002,member_2003) INSERT_METHOD=LAST;


INSERT_METHOD는 4.0이상부터 사용할 수 있으며 3가지를 지정할 수 있다. NO, FIRST, LAST
위에서는 LAST로 지정했는데, 이는 INSERT가 발생하면 UNION의 마지막에 지정한 테이블인 MEMBER_2003에
데이터가 INSERT됨을 의미한다. first: 처음에 지정한 테이블, no: insert금지
4.0이하라면 merge table이 아닌 각각의 테이블에 insert를 수행해야 한다.

mysql> select * from member_2000;
+--------------+---------------------+------------+
| id           | regdate             | name       |
+--------------+---------------------+------------+
| maddog2000   | 2000-01-01 00:00:00 | 강명규2000 |
| batman2000   | 2000-01-01 00:00:00 | 배트맨2000 |
| superman2000 | 2000-01-01 00:00:00 | 슈퍼맨2000 |
+--------------+---------------------+------------+
3 rows in set (0.00 sec)

mysql> select * from member_2001;
+--------------+---------------------+------------+
| id           | regdate             | name       |
+--------------+---------------------+------------+
| maddog2001   | 2001-01-01 00:00:00 | 강명규2001 |
| batman2001   | 2001-01-01 00:00:00 | 배트맨2001 |
| superman2001 | 2001-01-01 00:00:00 | 슈퍼맨2001 |
+--------------+---------------------+------------+
3 rows in set (0.00 sec)

mysql> select * from member_2002;
+--------------+---------------------+------------+
| id           | regdate             | name       |
+--------------+---------------------+------------+
| maddog2002   | 2002-01-01 00:00:00 | 강명규2002 |
| batman2002   | 2002-01-01 00:00:00 | 배트맨2002 |
| superman2002 | 2002-01-01 00:00:00 | 슈퍼맨2002 |
+--------------+---------------------+------------+
3 rows in set (0.00 sec)

mysql> select * from member_2003;
+--------------+---------------------+------------+
| id           | regdate             | name       |
+--------------+---------------------+------------+
| maddog2003   | 2003-01-01 00:00:00 | 강명규2003 |
| batman2003   | 2003-01-01 00:00:00 | 배트맨2003 |
| superman2003 | 2003-01-01 00:00:00 | 슈퍼맨2003 |
+--------------+---------------------+------------+
3 rows in set (0.00 sec)

mysql> select * from member_all;
+--------------+---------------------+------------+
| id           | regdate             | name       |
+--------------+---------------------+------------+
| maddog2000   | 2000-01-01 00:00:00 | 강명규2000 |
| batman2000   | 2000-01-01 00:00:00 | 배트맨2000 |
| superman2000 | 2000-01-01 00:00:00 | 슈퍼맨2000 |
| maddog2001   | 2001-01-01 00:00:00 | 강명규2001 |
| batman2001   | 2001-01-01 00:00:00 | 배트맨2001 |
| superman2001 | 2001-01-01 00:00:00 | 슈퍼맨2001 |
| maddog2002   | 2002-01-01 00:00:00 | 강명규2002 |
| batman2002   | 2002-01-01 00:00:00 | 배트맨2002 |
| superman2002 | 2002-01-01 00:00:00 | 슈퍼맨2002 |
| maddog2003   | 2003-01-01 00:00:00 | 강명규2003 |
| batman2003   | 2003-01-01 00:00:00 | 배트맨2003 |
| superman2003 | 2003-01-01 00:00:00 | 슈퍼맨2003 |
+--------------+---------------------+------------+
12 rows in set (0.00 sec)


이제 insert하면 어떻게 되는지 함 보자. 위에서 지정했듯이 member_2003에 insert된다.
mysql> insert into member_all values('member_new', now(), '강명규');
Query OK, 1 row affected (0.01 sec)

mysql> select * from member_all;
+--------------+---------------------+------------+
| id           | regdate             | name       |
+--------------+---------------------+------------+
| maddog2000   | 2000-01-01 00:00:00 | 강명규2000 |
| batman2000   | 2000-01-01 00:00:00 | 배트맨2000 |
| superman2000 | 2000-01-01 00:00:00 | 슈퍼맨2000 |
| maddog2001   | 2001-01-01 00:00:00 | 강명규2001 |
| batman2001   | 2001-01-01 00:00:00 | 배트맨2001 |
| superman2001 | 2001-01-01 00:00:00 | 슈퍼맨2001 |
| maddog2002   | 2002-01-01 00:00:00 | 강명규2002 |
| batman2002   | 2002-01-01 00:00:00 | 배트맨2002 |
| superman2002 | 2002-01-01 00:00:00 | 슈퍼맨2002 |
| maddog2003   | 2003-01-01 00:00:00 | 강명규2003 |
| batman2003   | 2003-01-01 00:00:00 | 배트맨2003 |
| superman2003 | 2003-01-01 00:00:00 | 슈퍼맨2003 |
| member_new   | 2003-02-18 16:27:15 | 강명규     |
+--------------+---------------------+------------+
13 rows in set (0.00 sec)

mysql> select * from member_2003;
+--------------+---------------------+------------+
| id           | regdate             | name       |
+--------------+---------------------+------------+
| maddog2003   | 2003-01-01 00:00:00 | 강명규2003 |
| batman2003   | 2003-01-01 00:00:00 | 배트맨2003 |
| superman2003 | 2003-01-01 00:00:00 | 슈퍼맨2003 |
| member_new   | 2003-02-18 16:27:15 | 강명규     |
+--------------+---------------------+------------+
4 rows in set (0.00 sec)

mysql>


위의 테이블을 보면 2003년도의 데이터만이 UPDATE연산이 발생하고, 나머지 테이블인
member_2000, member_2001, member_2002등은 주로 select만이 발생한다.
따라서 member_2003을 제외한 테이블등은 mysql쉘명령인 myisampack을 사용하여 압축시켜두면
공간의 절약할 수 있다. 테스트에는 member_2000에만 myisampack을 사용하여 압축해봤다.
row가 너무 작으면 압축이 수행되지 않으므로, 2000개의 row를 추가적으로 insert한 후에 테스트했다.

insert into member_2000 values('a0001',date_add('2000-01-01 00:00:00', interval 1    minute),'a0001');
insert into member_2000 values('a0002',date_add('2000-01-01 00:00:00', interval 2    minute),'a0002');
.
.
insert into member_2000 values('a1999',date_add('2000-01-01 00:00:00', interval 1999 minute),'a1999');
insert into member_2000 values('a2000',date_add('2000-01-01 00:00:00', interval 2000 minute),'a2000');


C:mysqldatadbakorea>dir member_*
C 드라이브의 볼륨: WIN2000
볼륨 일련 번호: F845-C077

C:mysqldatadbakorea 디렉터리

2003-02-18  04:21p               8,604 member_2000.frm
2003-02-18  05:05p              56,112 member_2000.MYD
2003-02-18  05:04p              29,696 member_2000.MYI
2003-02-18  04:21p               8,604 member_2001.frm
2003-02-18  04:21p                 112 member_2001.MYD
2003-02-18  04:26p               2,048 member_2001.MYI
2003-02-18  04:21p               8,604 member_2002.frm
2003-02-18  04:21p                 112 member_2002.MYD
2003-02-18  04:26p               2,048 member_2002.MYI
2003-02-18  04:21p               8,604 member_2003.frm
2003-02-18  04:27p                 144 member_2003.MYD
2003-02-18  04:56p               2,048 member_2003.MYI
2003-02-18  04:22p               8,604 member_all.frm
2003-02-18  04:22p                  68 member_all.MRG
              14개 파일         135,408 바이트
               0 디렉터리  12,436,623,360 바이트 남음

C:mysqldatadbakorea>c:mysqlinmyisamchk -dvv member_2000

MyISAM file:         member_2000
Record format:       Packed
Character set:       latin1 (8)
File-version:        1
Creation time:       2003-02-18 16:21:45
Status:              open,changed
Data records:                 2003  Deleted blocks:                 0
Datafile parts:               2003  Deleted data:                   0
Datafile pointer (bytes):        4  Keyfile pointer (bytes):        4
Datafile length:             56112  Keyfile length:             29696
Max datafile length:    4294967294  Max keyfile length: 4398046510079
Recordlength:                   36

table description:
Key Start Len Index   Type                     Rec/key         Root  Blocksize
1   2     15  multip. char packed stripped NULL          0         3072       1024

Field Start Length Nullpos Nullbit Type
1     1     1
2     2     15     1       1       no endspace
3     17    8      1       2       no zeros
4     25    12     1       4       no endspace


데이터베이스를 shutdown후 다음 작업을 수행한다.

C:mysqldatadbakorea>c:mysqlinmyisampack member_2000.myi
Compressing member_2000.MYD: (2003 records)
- Calculating statistics
- Compressing file
61.7%
Remember to run myisamchk -rq on compressed tables

C:mysqldatadbakorea>dir member_2000*
C 드라이브의 볼륨: WIN2000
볼륨 일련 번호: F845-C077

C:mysqldatadbakorea 디렉터리

2003-02-18  04:21p               8,604 member_2000.frm
2003-02-18  05:05p              21,497 member_2000.MYD
2003-02-18  05:09p               1,024 member_2000.MYI
               3개 파일          31,125 바이트
               0 디렉터리  12,436,697,088 바이트 남음

C:mysqldatadbakorea>c:mysqlinmyisamchk -rq member_2000
- check key delete-chain
- check record delete-chain
- recovering (with sort) MyISAM-table 'member_2000'
Data records: 2003
- Fixing index 1

C:mysqldatadbakorea>c:mysqlinmyisamchk -dvv member_2000

MyISAM file:         member_2000
Record format:       Compressed
Character set:       latin1 (8)
File-version:        1
Creation time:       2003-02-18 16:21:45
Recover time:        2003-02-18 17:10:42
Status:              checked,analyzed,optimized keys
Checksum:               1818400583
Data records:                 2003  Deleted blocks:                 0
Datafile parts:               2003  Deleted data:                   0
Datafile pointer (bytes):        4  Keyfile pointer (bytes):        2
Datafile length:             21490  Keyfile length:             17408
Max datafile length:    4294967294  Max keyfile length:      67107839
Recordlength:                   36

table description:
Key Start Len Index   Type                     Rec/key         Root  Blocksize
1   2     15  multip. char packed stripped NULL          0        16384       1024

Field Start Length Nullpos Nullbit Type                         Huff tree  Bits
1     1     1                      constant                             1     0
2     2     15     1       1       no endspace                          2     9
3     17    8      1       2       zerofill(2)                          3     9
4     25    12     1       4       no endspace                          2     9

C:mysqldatadbakorea>


mysql> select year(regdate) as year, count(*) as entries from member_all group by year;
+------+---------+
| year | entries |
+------+---------+
| 2000 |    2003 |
| 2001 |       3 |
| 2002 |       3 |
| 2003 |       4 |
+------+---------+
4 rows in set (0.06 sec)

member_2000테이블은 isampack에 의해 read only로 변했으므로 insert는 할 수 없다.
mysql> insert into member_2000 values('a2001',date_add('2000-01-01 00:00:00', interval 2001 minute), 'a2001');
ERROR 1036: Table 'member_2000' is read only

테스트를 마쳤으면 작업한 테이블들을 지워버리자.(하위버전은 multiple table drop을 지원하지 않음)
mysql> drop table member_all, member_2003, member_2002, member_2001, member_2000;
Query OK, 0 rows affected (0.06 sec)

This article comes from dbakorea.pe.kr (Leave this line as is)

[원글링크] : https://www.linux.co.kr/home2/board/subbs/board.php?bo_table=lecture&wr_id=232


이 글을 트위터로 보내기 이 글을 페이스북으로 보내기 이 글을 미투데이로 보내기

 
강명규
홈페이지 : http://dbakorea.pe.kr/

e-mail : myunggyu골뺑이orgio.net