웹이 점점 커지고 다양한 요구가 생겨나는 가운데 NoSQL이 커다란 이슈중에 하나로 떠오르고 있습니다. 제가 NoSQL에 대해서 처음 들은 것은 올 초정도로 기억하고 있습니다.

Google Trends에서 NoSQL로 검색한 결과

구글 트랜즈 에서 확인해보아도 NoSQL이라는 단어가 이슈화되기 시작한 것은 2009년 중순정도로 나타나고 있습니다.  위키피디아 에서 확인해 보면 NoSQL이라는 단어는 1998년 Carlo Strozzi이 SQL을 드러내지 않는 경량 데이터베이스로 이름지었고 2009년 초에 Last.fm 의 Johan Oskarsson이 오픈소스 분산데이터베이스에 대한 논의를 위한 이벤트를 원했을 때 Rackspace 의 직원인 Eric Evans가 NoSQL이라는 단어를 다시 소개했다고 합니다. 아틀란타에서 열린 no:sql conference 2009가 NoSQL논의에 큰 영향을 미쳤다고 합니다. (이 컨퍼런스의 모토인 "select fun, profit from real_world where relational=false;"가 상당히 센스넘치는군요)

올해 중에 NoSQL중 하나는 경험해 보자는 생각이었는데 마침 좀 만져볼 기회가 생겨서 좀 만져보고 있습니다. 개념자체가 개발자에게 기존에 익숙한 RDBMS와는 너무 달라서 튜토리얼 보고 단순한 사용정도는 할 수 있겠지만 관련해서 고민해 보려면 NoSQL에 대해서 좀 자세히 알아야 할 필요가 있게 느껴졌습니다. 사실 NoSQL에 대한 지식이 많다보니 고민 자체가 해결책이나 진도나 나가지 않고 계속 빙글빙글 도는 느낌이라 여기저기 자료를 좀 찾아서 정리해 보았습니다.





CAP Theorem
NoSQL에 대해서 이해하려면 먼저 CAP 이론에 대해서 알 필요가 있습니다. CAP이론은 Brewer's CAP Theorem 으로 알려져 있는데 분산 컴퓨팅 시스템에서 보장해야 하는 특징으로 아래 3가지를 정의하고 있습니다.

  • Consistency (일관성) : 모든 노드들은 동시에 같은 데이터를 보아야 합니다.
  • Availability (유효성) : 모든 노드는 항상 읽기와 쓰기를 할 수 있어야 합니다.
  • Partition Tolerance (파티션 허용차) : 시스템은 물리적인 네트워크 파티션을 넘어서도 잘 동작하여야 합니다

CAP 이론에 따르면 위 3가지 중에 동시에 2가지만 보장할수 있고 3개를 모두 보장하는 것이 불가능하다고 나와있습니다. 그래서 데이터를 관리할때 이 3가지 중에 어느 2가지에 중점을 두냐는 것은 아주 중요한 부분입니다. 이 부분을 이해하는데 Nathan Hurst 이 만든 아래의  Visual Guide to NoSQL Systems 는 큰 도움이 됩니다.

사용자 삽입 이미지

기존에 많이 사용하던 RDBMS는 3가지 중 CA에 집중하고 있습니다. 웹이 발전하면서 다양한 요구사항이 생겨나고 엄청난 양의 데이터를 처리해야 하게 되면서 RDBMS가 갖지 못한 P의 특성이 필요해졌고 그러면서 등장한 것이 NoSQL입니다. 좀더 풀어쓰면 데이터베이스에 대한 수평적 확장(Horizontal Scalability 즉 옆에 서버한대 더 배치해서 데이터베이스를 늘리고 싶다는 의미입니다.)에 대한 이슈가 발생했고 확장성이슈를 해결하기 위해서 P를 선택하다 보니 기존에 가지고 있던 C나 A의 특성중 하나를 포기해야 했습니다. 그래서 NoSQL에는 다양한 시도들이 있지만 가장 중요한 이슈는 확장성을 해결하려는 것으로 생각됩니다.

관계형 데이터베이스는 기본적으로 분산형을 고려해서 디자인 되지 않았습니다. 그래서 ACID(원자성, 일관성, 독립성, 지속성) 트랜잭션 같은 추상화와 고레벨 쿼리모델을 풍부하게 제공할 수 있지만 확장성이 좋지 못하기 때문에 모든 NoSQL 데이터베이스는 다양한 방법으로 확장성 이슈를 해결하기 위해 초점을 맞추고 있습니다. 각 NoSQL에는 여러가지 차이점들이 있지만 CAP의 범주에서만 보면 CP를 선택하거나 AP를 선택하게 됩니다.




왜 비관계형이어야 하는가?
NoSQL이 확장성 이슈를 해결하려고 CP나 AP의 특성을 선택했지만 구체적으로 어떤 특징을 선택하고 왜 그래야 했는지 이해할 필요가 있습니다. NoSQL은 많은 제품군들이 있는데 모두 같은 전략으로 접근하고 있지는 않고 각각에 제품에 따라 다양한 접근을 하고 있는데 아래 적힌 내용들은 비관계형으로 가기 위한 여러가지 특성들에 대한 이야기이고 제품군에 따라 아래의 특성들을 선택한 여부는 다른 것으로 보입니다. 아래의 내용은 상당부분 VINEET GUPTA가 작성한 NoSql Databases - Part 1 - Landscape 를 참고하였습니다. 잘 정리된 문서라서 참고하시면 도움이 될 것입니다.



관계형 데이터 베이스는 확장하기가 어렵습니다.

Replication - 복제에 의한 확장
Master-Slave 구조에서는 결과를 슬레이브의 갯수만큼 복제해야 하는데 N개의 슬레이브에서 읽을 수 있기 때문에 Read는 빠르지만 Write에서는 병목현상이 발생하게 기 때문에 확장성에 대한 제한을 가지게 됩니다.
다중 마스터구조에서는 마스터를 추가함으로써 쓰기의 성능을 향상시킬 수 있는데 대신에 충돌이 발생할 가능성이 생기게 됩니다.

Partitioning(Sharding) - 분할에 의한 확장
Read만큼 Write도 확장할 수 있지만 애플리케이션레이어에서 파티션된 것을 인지하고 있어야 합니다. RDBMS의 가치는 관계에 있다고 할 수 있는데 파티션을 하면 이 관계가 깨져버리고 각 파티션된 조각간에 조인을 할 수 없기 때문에 관계에 대한 부분은 애플리케이션 레이어에서 책임져야 합니다. 일반적으로  RDBMS에서 수동  Sharding 은 쉽지 않습니다.



필요없는 특성들

UPDATE와 DELETE
Update와 Delete는 전통적으로 정보의 손실이 발생하기 때문에 잘 사용되지 않으며 후에 데이터 검사 및 재활성화를 위해서 기록해둘 필요가 있습니다. 그리고 사용자가 커뮤니티를 탈퇴한다고 그들의 글을 지우지 않듯이 도메인 관점에서는 실제로 삭제되지 않습니다.  이런 접근을 하게 되면 Update / Delete를 모두 Insert로 모델할수 있고 과거 데이터는 버전을 붙혀서 기록할 수 있으며 이 데이터들은 비활성데이터들이 됩니다. 이 INSET-only 시스템에서는 2개의 문제가 있는데 데이터베이스에서 종속(cascade)에 대한 트리거를 이용할 수 없으며 Query가 비활성 데이터를 걸러내야 할 필요가 있습니다.

JOIN
데이터가 많을 때 JOIN은 많은 양의 데이터에 복잡한 연산을 수행해야 하기 때문에 비용이 많이 들며 파티션을 넘어서는 동작되지 않기 때문에 피해야 합니다. 정규화는 일관된 데이터를 가지기 쉽게 하고 스토리지의 양을 줄이기 위해서 하는건데 반정규화(De-normalization)를 하면 JOIN문제를 피할 수 있습니다. 반정규화로 일관성에 대한 책임을 디비에서 애플리케이션으로 이동시킬수 있는데 이는 INSERT-only라면 어렵지 않습니다.

ACID 트랜젝션
Atomic (원자성) : 여러 레코드를 수정할 때 원자성은 필요없으며 단일키 원자성이면 충분합니다.
Consistency (일관성) : 대부분의 시스템은 C보다는 P나 A를 필요로 하기 때문에 엄격한 일관성을 가질 필요는 없고 대신 결과의 일관성(Eventually Consistent )을 가질 수 있습니다.
Isolation (격리성) : 읽기에 최선을 다하는(Read-Committe) 것 이상의 격리성은 필요하지 않으며 단일키 원자성이 더 쉽습니다.
Durability (지속성) : 각 노드가 실패했을때도 이용되기 위해서는 메모리가 데이터를 충분히 보관할 수 있을정도로 저렴해지는 시점까지는 지속성이 필요합니다.

고정된 스키마
RDBMS에서는 데이터를 사용하기 전에 스키마를 정의해야하고 Index등을 정의해야 하는데 현재의 웹환경에서는 빠르게 새로운 피쳐를 추가하고 이미 존재하는 피쳐를 조정하기 위해서는 스키마 수정이 필수적으로 요구됩니다. 하지만 컬럼의 추가/수정/삭제는 row에 lock을 걸고 index의 수정은 테이블에 락을 걸기 때문에 스키마 수정이 어렵습니다.



어떤 특성들은 갖지 않습니다.
계층화 데이터나 그래프를 모델하는 것은 어렵습니다. 또한 빠른 응답을 위해서 디스크를 피하고 메인 메모리에서 데이터를 제공하는 것이 바람직한데 대부분의 관계형 데이터베이스는 디스크기반이기 때문에 쿼리들이 디스크에서 수행됩니다.





기대하는 특성들
NoSQL이 바라는 환경은 서버들이 다른 용량들을 가지고 수업이 퍼져나가는 것으로 이를 노드라고 부릅니다.

높은 확장성
점진적으로 노드를 추가할 수 있어야 하고 이는 파티셔닝을 통해서 가능합니다.

높은 Availability
실패의 단일포인트가 없으며 데이터는 복제되기 때문에 어떤 노드가 죽었을때도 데이터는 이용이 가능합니다.

높은 성능
디스크대신 메모리 기반으로 결과는 빠르게 리턴되어야 하며 이는 논블락킹 Write와 낮은 복잡성을 가진 알고리즘을 통해서 이룰수 있습니다.

원자성
각각의 쓰기는 원자성을 가질 필요가 있다.

일관성
강한 일관정은 필요없고 결과적인 일관성만 가지면 된다.(Read-Your-Writes1 일관성)

지속성
데이터는 휘말성 메모리만이 아닌 디스크에서 유지되어야 합니다.

배포의 유연함(Flexibility)
노드의 추가/삭제는 데이터를 분산하고 수동으로 중재할 필요없이 자동적으로 로드되어야 하며 분산 파일 시스템이나 공유스토리지 요구같은 제약이나 특수한 하드웨어같은 것이 필요없어야 합니다. 이기종간의 하드웨어에서 동작가능해야 합니다.

모델링의 유연함(Flexibility)
Key-Value쌍, 계층형 데이터, 그래프등 여러가지 타입의 데이터를 간단하게 모델할 수 있어야 합니다.

쿼리의 유연함(Flexibility)
하나의 호출에서 제공된 키에 대한 값이 묶음을 얻는 다중 GET과 키의 특정 범위에 기반한 데이터를 얻는 범위 쿼리가 필요합니다.


이 포스팅은 NoSQL에 대해서 #2로 이어집니다.
Footnote.
  1. Read-Your-Writes(RYW) 일관성은 레코드가 업데이트 되었을때 그 레코드에 대한 읽기시도는 업데이트된 값을 돌려주는 것을 보장해주는 것의 의미합니다. [Back]
2010/09/18 23:57 2010/09/18 23:57
크리에이티브 커먼즈 라이센스
Creative Commons License

'Database' 카테고리의 다른 글

DROP, DELETE, TRUNCATE의 차이점  (0) 2011.06.29
NoSQL에 대해서 #2  (0) 2011.06.09
초보 관리자/DB 2009/01/29 11:24 by 비트센스
 
짬짬히 이런 저런 작업을 하면서 글을 쓰기 때문에,
실제 사용하는 것만 올립니다. 덕분에 글이 짧네요.

MSSQL에서 날짜 연산 방법입니다.

예. 어제 일자를 알고 싶다.
select getdate(), dateadd(d, -1, getdate())
쉽죠? ^^;;

연산 날짜 부분(datepart) 인지는 몇개 없습니다.

yy : 년
mm : 월
dy, y : dayofyear (먼지 잘 모르겠음)
d : 일
wk : 주
hh : 시
mi, n : 분
s : 초
ms : 밀리세컨드

declare @날자 datetime

set @날자='2008-01-01'

---현재월의 초일 --
SELECT dateadd(d,-day(@날자)+1,@날자)

---현재월의 말일 --
SELECT dateadd(d,-day(dateadd(m,1,@날자)), dateadd(m,1,@날자))

---전월의 초일 --
SELECT dateadd(m,-1, dateadd(d,-day(@날자)+1,@날자))

---전월의 말일 --
SELECT dateadd(d,-day(@날자),@날자)

== 또다른 매달말일 구하는 법
SELECT CONVERT(Char(8), DateAdd(day, -1, DateAdd(month, 1, @종료월 + '01')), 112)

'Database > SQL-Server' 카테고리의 다른 글

DBCC 명령어  (0) 2011.06.29
DBCC CHECKDB, CHECKTABLE (손상된 테이블 복구)  (0) 2011.06.27
[MSSQL] 날짜 연산 DATEADD  (0) 2011.05.13
MSSQL Date Type Convert  (0) 2011.05.13
[MSSQL - SELECT 와 INSERT 동시 처리]  (0) 2011.05.09
0 Feb 22 2006 4:26PM CONVERT(CHAR(19), DATETIME, 0)
1 02/22/06 CONVERT(CHAR(8), DATETIME, 1)
2 06.02.22 CONVERT(CHAR(8), DATETIME, 2)
3 22/02/06 CONVERT(CHAR(8), DATETIME, 3)
4 22.02.06 CONVERT(CHAR(8), DATETIME, 4)
5 22-02-06 CONVERT(CHAR(8), DATETIME, 5)
6 22 Feb 06 CONVERT(CHAR(9), DATETIME, 6)
7 Feb 22, 06 CONVERT(CHAR(10), DATETIME, 7)
8 16:26:08 CONVERT(CHAR(8), DATETIME, 8)
9 Feb 22 2006 4:26:08:020PM CONVERT(CHAR(26), DATETIME, 9)
10 02-22-06 CONVERT(CHAR(8), DATETIME, 10)
11 06/02/22 CONVERT(CHAR(8), DATETIME, 11)
12 060222 CONVERT(CHAR(6), DATETIME, 12)
13 22 Feb 2006 16:26:08:020 CONVERT(CHAR(24), DATETIME, 13)
14 16:26:08:037 CONVERT(CHAR(12), DATETIME, 14)
20 2006-02-22 16:26:08 CONVERT(CHAR(19), DATETIME, 20)
21 2006-02-22 16:26:08.037 CONVERT(CHAR(23), DATETIME, 21)
22 02/22/06 4:26:08 PM CONVERT(CHAR(20), DATETIME, 22)
23 2006-02-22 CONVERT(CHAR(10), DATETIME, 23)
24 16:26:08 CONVERT(CHAR(8), DATETIME, 24)
25 2006-02-22 16:26:08.037 CONVERT(CHAR(23), DATETIME, 25)
100 Feb 22 2006 4:26PM CONVERT(CHAR(19), DATETIME, 100)
101 02/22/2006 CONVERT(CHAR(10), DATETIME, 101)
102 2006.02.22 CONVERT(CHAR(10), DATETIME, 102)
103 22/02/2006 CONVERT(CHAR(10), DATETIME, 103)
104 22.02.2006 CONVERT(CHAR(10), DATETIME, 104)
105 22-02-2006 CONVERT(CHAR(10), DATETIME, 105)
106 22 Feb 2006 CONVERT(CHAR(11), DATETIME, 106)
107 Feb 22, 2006 CONVERT(CHAR(12), DATETIME, 107)
108 16:26:08 CONVERT(CHAR(8), DATETIME, 108)
109 Feb 22 2006 4:26:08:067PM CONVERT(CHAR(26), DATETIME, 109)
110 02-22-2006 CONVERT(CHAR(10), DATETIME, 110)
111 2006/02/22 CONVERT(CHAR(10), DATETIME, 111)
112 20060222 CONVERT(CHAR(8), DATETIME, 112)
113 22 Feb 2006 16:26:08:067 CONVERT(CHAR(24), DATETIME, 113)
114 16:26:08:067 CONVERT(CHAR(12), DATETIME, 114)
120 2006-02-22 16:26:08 CONVERT(CHAR(19), DATETIME, 120)
121 2006-02-22 16:26:08.080 CONVERT(CHAR(23), DATETIME, 121)
126 2006-02-22T16:26:08.080 CONVERT(CHAR(23), DATETIME, 126)
127 2006-02-22T16:26:08.080 CONVERT(CHAR(23), DATETIME, 127)
130 24 ???? 1427 4:26:08:080PM CONVERT(CHAR(32), DATETIME, 130)
131 24/01/1427 4:26:08:080PM CONVERT(CHAR(25), DATETIME, 131)


[MSSQL - SELECT 와 INSERT 동시 처리]

편의상 아래와 같은 세개의 테이블이 있다고 가정하겠습니다.

CREATE TABLE [dbo].[table_a] (
[seq] [int] PRIMARY KEY NOT NULL,
[Name] [varchar] (70) NOT NULL,
[Email] [varchar] (70) NOT NULL,
[Idate] [datetime] NOT NULL
)

CREATE TABLE [dbo].[table_b] (
[seq] [int] PRIMARY KEY NOT NULL,
[Name] [varchar] (70) NOT NULL,
[Email] [varchar] (70) NOT NULL,
[Idate] [datetime] NOT NULL
)


CREATE TABLE [dbo].[table_c] (
[seq] [int] PRIMARY KEY NOT NULL,
[Name] [varchar] (70) NOT NULL,
[Nickname] [varchar] (255) NULL,
[Email] [varchar] (70) NOT NULL,
[Tel] [varchar] (20) NULL,
[Idate] [datetime] NOT NULL
)

첫번째와 두번째의 테이블인 table_atable_b 는 컬럼의 갯수 및 데이터형식이 똑 같은 쌍동이 테이블입니다., table_c두개의 컬럼(Nickname, Tel)이 더 추가되어 있는 테이블로 table_atable_c 와는 조금 다른 구조를
가지고 있습니다.



1. 두 테이블의 컬럼이 같을때 SELECT INSERT 하기

두개의 테이블간에 컬럼이 table_a 와 table _b 처럼 완전히 일치할 때는 아래와 같이 간단하게 처리할 수 있습니다.

-- 사용법

INSERT INTO [입력될 테이블명] SELECT * FROM [검색되는 테이블명]

예1) INSERT INTO table_b SELECT * FROM table_a

위의 예1) 에서는 table_a 의 레코드 전체를 table_b 로 삽입(INSERT) 시킵니다. 만약에 조건을 주어 데이터를 삽입(INSERT) 시키려 한다면 아래와 같이 뒤에 WHERE 절만 추가해 주시면 됩니다.

예2)
INSERT INTO table_b SELECT * FROM table_a WHERE seq = 2

위의 SQL 문은 table_a 에서 seq 의 값이 2 인 레코드를 table_b 에 INSERT 시킵니다.



2 . 두 테이블간의 컬럼이 일치하지 않을때 SELECT INSERT 하기


두개의 테이블간에 컬럼이 table_a 와 table _c 처럼 일치하지 않을때는 아래와 같이 컬럼명을 지정해 주시면됩니다.

-- 사용법

INSERT INTO [입력될 테이블명] (컬럼1, 컬럼2, ... ) SELECT 컬럼1, 컬럼2, ... FROM [검색되는 테이블명]

예3) INSERT INTO table_c ( seq, Name, Email, Idate ) SELECT seq, Name, Email, Idate FROM table_a

위의 예3) 에서는 table_a 의 컬럼중 seq, Name, Email, Idate 컬럼을 table_c 에 Insert 시키고 있습니다. 한가지 주의
할 것은 table_c 의 구조가 table_b 와 다른 만큼 INSERT 될 컬럼이 SELECT 되는 컬럼과 일치하지 않으면 아래와 같은
에러가 발생하게 됩니다.

서버: 메시지 213, 수준 16, 상태 4, 줄 1
삽입 오류: 제공된 값의 개수나 열 이름이 테이블 정의와 일치하지 않습니다.




3.
SELECT INTO 를 이용한 데이터 삽입

위에서 설명한 SELECT INSERT 는 테이블의 검색결과를 이미 존재하는 테이블에 삽입(INSERT) 하게됩니다.하지만 SELECT INTO 는 테이블의 검색결과를 INTO 문 다음에 지정한 테이블을 새로 생성시켜서 삽입하게 됩니다. INTO 문 다음의 테이블은 반드시 존재하지 않아야 합니다. 존재하는 테이블이라면 아래와 같은 에러가 발생하게 됩니다.

서버: 메시지 2714, 수준 16, 상태 6, 줄 1
데이터베이스에 'table_d'(이)라는 개체가 이미 있습니다.

-- 사용법

SELECT * INTO [생성될 테이블명] FROM [검색되는 테이블명]

예4) SELECT * INTO table_d FROM table_a

위의 예4) 에서는 table_a 의 내용을 table_d라는 테이블을 새로 생성시켜서 삽입하게 됩니다. 조건절을 추가하려면
검색되는 테이블명 뒤에 추가하면 됩니다.

예5)
SELECT * INTO table_d FROM table_a
WHERE seq = 3

위의 SQL 문은 table_a 에서 seq 의 값이 3인 레코드를 새로 생성되는 table_d 에 INSERT 시킵니다.

 

작성자: 웹마당넷(webmadang@webmadang.net)   http://www.webmadang.net 

'Database > SQL-Server' 카테고리의 다른 글

DBCC 명령어  (0) 2011.06.29
DBCC CHECKDB, CHECKTABLE (손상된 테이블 복구)  (0) 2011.06.27
[MSSQL] 날짜 연산 DATEADD  (0) 2011.05.13
MSSQL dateadd() 이용하여 말일, 초일 구해보자  (0) 2011.05.13
MSSQL Date Type Convert  (0) 2011.05.13

혹 이런 고민에 빠진 독자가 있을지 모르지만, SELECT, UPDATE, DELETE 등의 SQL의 예약어를 테이블의 이름이나 열 이름으로 사용해야 할 경우가 있다면 이 기사가 도움이 될 것이다.

기본적으로 예약어들을 사용한다는 것은 이후 관리상의 문제나 여러 가지 문제를 발생시키기 때문에 사용하지 않는 것이 좋다.


하지만 아쉽게도 다른 데이터베이스에서 SQL Server 등으로 마이그레이션을 했을 때 예약어가 테이블명이나 필드명으로 사용되어 어쩔 수 없이 이용해야 한다면  다음과 같이 이용할 수 있다.

SQL Server에서 열 이름은 "["과 "]"로 묶어 표기하면 데이터베이스 객체 이름으로 인식된다.
오라클에서 사용하고 싶다면 큰따옴표로 묶어 기술하면 된다.


Test 테이블에 FROM 필드와 TO열을 생성하고 싶다면 다음과 같은 명령어가 필요하다.

  • SQL Server일 경우
  • CREATE TABLE test ( [FROM] int null, [TO] int null )
     
  • Oracle일 경우
  • CREATE TABLE test ( "FROM" NUMBER(8) null, "TO" NUMBER(8) null )

이를 통해 FROM필드와 TO필드를 가진 테이블이 생성된다. SELECT나 UPDATE에서도 같은 서식을 사용하여 이용할 수 있다.

  • SQL Server일 경우
  • SELECT [FROM] FROM test WHERE [TO] = 45
     
  • Oracle일 경우
  • SELECT "FROM" FROM test WHERE "TO" = 45

* 테이블명이나 필드명등에 공백문자열이 포함되어 두단어 이상으로 사용하고 싶을때도 []를 사용하면 된다.

 

자료출처 : http://korea.internet.com

SQL> create tablespace ts1
  2  datafile '/home/oracle/ts1.dbf' size 10M;

테이블스페이스가 생성되었습니다.

10M 할당된 테이블스페이스가 생성되었다

 

 SQL> create table t1
  2  (id number)
  3  tablespace ts1;

테이블이 생성되었습니다.

※ 참고로 테이블스페이스는 관리자가 생성하고 t1테이블은 유저가 만든것이다

(다시 말해 유저가 테이블을 만들수있게 관리자가 테이블스페이스를 할당했다고 생각하면 된다)

 

 SQL> select TABLE_NAME, TABLESPACE_NAME from user_tables;

TABLE_NAME      TABLESPACE_NAME
---------------    ---------------
T1                                TS1
DEPT                        USERS
EMP                         USERS
BONUS                     USERS
SALGRADE                USERS

 

T1 테이블에 데이터를 꽉 채워 본다

 SQL> insert into t1 select * from t1;

28 개의 행이 만들어졌습니다.

...

SQL> insert into t1 select * from t1;

114688 개의 행이 만들어졌습니다.

SQL> insert into t1 select * from t1;

229376 개의 행이 만들어졌습니다.

SQL> insert into t1 select * from t1;
insert into t1 select * from t1
*
1행에 오류:
ORA-01653: unable to extend table SCOTT.T1 by 128 in tablespace TS1

 

 이제 테이블스페이스를 확장시켜본다

  

 SQL> alter tablespace ts1 add
  2  datafile '/home/oracle/ts1_2.dbf' size 20M;

테이블스페이스가 변경되었습니다.

 

20M를 추가하여 기존의 10M와 함께 전체 30M가 되었다

 

 SQL> insert into t1 select * from t1;

458752 개의 행이 만들어졌습니다.

 데이터가 더 들어가진다!!

다시 계속 집어넣는다

 

SQL> ALTER DATABASE DATAFILE '/home/oracle/ts1.dbf' RESIZE 30M;

데이타베이스가 변경되었습니다.

SQL> ALTER DATABASE DATAFILE '/home/oracle/ts1.dbf'

2 AUTOEXTEND ON NEXT 10M MAXSIZE 100M;

데이타베이스가 변경되었습니다.

 

 SQL> insert into t1 select * from t1;

1835008 개의 행이 만들어졌습니다.

 계속 들어간다...

 

 테이블 t1의 크기는

SQL> show parameter db_block_size

NAME                                 TYPE               VALUE
---------------------- ----------------- ---------------
db_block_size                        integer               8192


SQL> desc dba_extents
 이름                                               널?      유형
 -------------------------------- -------- ------------
 OWNER                                                    VARCHAR2(30)
 SEGMENT_NAME                                     VARCHAR2(81)
 PARTITION_NAME                                     VARCHAR2(30)
 SEGMENT_TYPE                                       VARCHAR2(18)
 TABLESPACE_NAME                                 VARCHAR2(30)
 EXTENT_ID                                                   NUMBER
 FILE_ID                                                         NUMBER
 BLOCK_ID                                                     NUMBER
 BYTES                                                         NUMBER
 BLOCKS                                                       NUMBER
 RELATIVE_FNO                                             NUMBER

 

SQL> select sum(blocks) from dba_extents
  2  where segment_name = 'T1';

SUM(BLOCKS)
-----------
      14336

 

SQL> select 14336 * 8192 from dual;

14336*8192
----------
 117440512

 대략..120메가 정도 된다...

[테이블스페이스 생성하기]

create tablespace data1 datafile '/oracle/oradata/stone/data1.dbf' size  6M
default storage (initial 50k next 50k minextents 10 maxextents 121 pctincrease 0);

테이블 스페이스는 locally managed tablespace를 사용하구요.   

uniform extent size 옵션과 함께 사용하면 데이터들이 각 disk에 고르게 분산이 되어 저장 됩니다.

 

물론 아시겠지만 가장 좋은 분산 방법은 hardware혹은 file system의 기능을 사용한 raid 1+0 입니다.

 

[테이블스페이스 삭제하기]

-- 테이블스페이스 내용도 지우고 데이터파일도 같이 지우기

drop tablespace tsdiskdiary01 including contents and datafiles;

drop tablespace SAMPLE_STONE including contents;

 

-- 테이블스페이스 정보보기
select  tablespace_name, block_size, initial_extent, next_extent, min_extents, max_extents, pct_increase, status from   dba_tablespaces;
select * from dba_data_files;
select * from dba_tablespaces;
select * from v$datafile;

-- 테이블스페이스 만들기
create tablespace data1 datafile '/oracle/oradata/stone/data1.dbf' size  6M
default storage (initial 50k next 50k minextents 10 maxextents 121 pctincrease 0);
/*
initial 50k => 처음 생성되는 익스텐트의 크기
next 50k => 현재 존재하는 마지막 익스텐트 다음에 생성될 익스텐트에 할당할 크기
minextents 10 => 세그먼트가 생성될 때 할당되어야 하는 익스텐트의 수
maxextents 121 => 오라클이 객체에 대해 할당할수 있는 익스텐트의 최대수
pctincrease 0 => 마지막 익스텐트 다음에 생성될 익스텐트의 증가율
*/

-- 테이블스페이스 만들기
create tablespace idx1 datafile '/oracle/oradata/stone/idx1.dbf' size  6M
default storage (initial 50k next 50k pctincrease 0);

create tablespace rds datafile '/oracle/oradata/stone/rds.dbf' size  6M
default storage (initial 50k next 50k pctincrease 0);
-- temp 테이블 스페이스는 안 만들어진다.
create tablespace temp datafile '/oracle/oradata/stone/temp.dbf' size  3M
temporary;


alter tablespace data1 add datafile '/oracle/oradata/stone/data11.dbf' size  3M;
-- 테이블스페이스에 새로운 파일 추가
create tablespace test
 datafile '/oracle/oradata/stone/test.dbf' size 1m;

drop tablespace test;

-- 기존에 있는 데이터파일을 테이블스페이스 파일로 다시 사용한다.
alter tablespace data1
 add datafile  '/oracle/oradata/stone/test.dbf' reuse;

-- 데이터파일의 크기를 늘린다.
alter database datafile
 '/oracle/oradata/stone/test.dbf' resize 1m;

-- 자동으로 증가하는 테이블스페이스 만들기
alter database datafile '/oracle/oradata/stone/test.dbf'
 autoextend on;

-- 테이블스페이스 생성하기
create tablespace app1_data
 datafile '/oracle/oradata/stone/app101.dbf' size 1024k;

create tablespace appl_data
 datafile '/oracle/oradata/stone/appl01.dbf' size 100k;


-- 테이블스페이스 관련 정보보기
select * from dba_tablespaces where tablespace_name = 'TEMP';
-- 얼마의 용량이 남았는지 확인하기
select * from dba_free_space where tablespace_name = 'TEMP';

-- appl_data 테이블스페이스에 test 테이블 만들기 100k 이상하면 에러가 난다..
create table test (num number)
 tablespace appl_data
 storage (initial 50k);

select * from dba_free_space where tablespace_name = 'APP1_DATA';
select * from user_segments where segment_name = 'TEST';

-- 데이터파일 확인하기
select * from dba_data_files;

select * from dba_rollback_segs;

select * from dba_roles;
-- connect, RESOURCE, DBA 역할에 주어진 권한 확인하기
select * from dba_sys_privs where grantee = 'CONNECT';
select * from dba_sys_privs where grantee = 'RESOURCE';
select * from dba_sys_privs where grantee = 'DBA';
select * from dba_users;
-- 사용자에 할당된 테이블스페이스 영역
select * from user_ts_quotas;
-- 사용자 세션 확인하기
select * from v$session;
-- 인덱스 확인하기
select * from user_indexes;

 

CREATE TABLESPACE tsdiskdiary01
DATAFILE '/oracle/oradata/stone/tsdiskdiary01.dbf' SIZE 100M
DEFAULT STORAGE
(INITIAL    10K
NEXT      10K
MINEXTENTS 2
MAXEXTENTS 50
PCTINCREASE 50);

 

[테이블스페이스 생성하기]

create tablespace tsdiskdiary01
datafile '/oracle/oradata/stone/tsdiskdiary01.dbf' size 500M
extent management local uniform size 1M;

create user diskdiary identified by diskdiary      -- 일반계정
    default tablespace tsdiskdiary01
    profile default;


grant connect, resource to diskdiary;

drop tablespace tsdiskdiary01 including contents and datafiles;

drop user diskdiary cascade;  
-- 데이터파일 추가하기
alter tablespace sample_stone add datafile  '/oracle/oradata/stone/sample_stone02.dbf' SIZE 200M

 

[테이블스페이스 용량 확인하기]

SELECT a.tablespace_name,
             a.total "Total(Mb)",
             a.total - b.free "Used(Mb)",
             nvl(b.free,0) "Free(Mb)",
             round((a.total - nvl(b.free,0))*100/total,0)  "Used(%)"
from     (select   tablespace_name, round((sum(bytes)/1024/1024),0) as total
             from     dba_data_files
             group   by tablespace_name) a,
           (select  tablespace_name, round((sum(bytes)/1024/1024),0) as free
            from      dba_free_space
            group by tablespace_name) b
where   a.tablespace_name = b.tablespace_name(+)
order by a.tablespace_name;

select SEGMENT_NAME, SEGMENT_TYPE, INITIAL_EXTENT, NEXT_EXTENT
   where TABLESPACE_NAME ='SAMPLE_STONE'
   and    SEGMENT_NAME= 'AAA ';

alter tablespace sample_stone add datafile  '/oracle/oradata/stone/sample_stone02.dbf' SIZE 200M


+ Recent posts