1. 데이터베이스 분류
1) RDBMS
- 테이블 기반, SQL 이용해서 작업
- 트리구조라서 깊이에 따라 조회 속도가 다름
2)NoSQL
- Not only SQL
- RDBMS 시스템의 주요 특성을 보장하는 ACID(Atomicity, Consistency, Isolation, Durability - Transaction의 주요 성질) 특성을 제공하지 않는 확장성이나 성능의 특성을 갖는 비관계형 데이터베이스
- 최근에는 NoSQL에 관계형 데이터베이스의 트랜잭션의 개념을 도입시키고 관계형 데이터베이스에도 NoSQL의 개념을 도입하는 형태로 발전하는 중
2. No SQL 종류
1) Key Value DB
- Key와 Value의 형태로 저장하는 데이터베이스
- Redis가 대표적인 Key Value 데이터베이스
2) Document DB
- 하나의 데이터를 하나의 문서로 취급
- Mongo DB가 대표적인 Document DB
3) Wide Column Store
- 열의 집합체를 만들 수 있는 데이터베이스
- HBase나 Cassandra가 대표적인 Wide Column Store
4) Graph DB
- 데이터에 그래프 자료구조를 도입한 데이터베이스
- SNS에 주로 이용
3. Mongo DB
1) 개요
- 데이터를 하나의 문서로 취급하는데 데이터를 표현할 때 JSON 표기법 사용
*JSON 표기법: 자바스크립트 객체표현법, 파이썬도 동일
배열: [데이터 나열]
객체(dict): {키:값, 키:값..}
Mongo DB는 자바스크립트 문법으로 데이터를 다룸
MEAN: 자바스클비트만으로 Web Application을 제작하는 기술
* Mongo DB, Express.js, Angular,js, node.js
MERN으로 변하는 중
* React
2) Docker를 이용해 설치
docker run --name 컨테이너이름 -v ~/data/data/db -d -p 27017:27017 mongo
- mongo 이미지를 다운로드 받아서 컨테이너 이름으로 생성
- data/data/db라는 디렉토리 데이터를 저장하고 백그라운드로 실행
- 27017 (mongo db의 기본 포트)로 접속
3) bash shell에 접속
- shell 중에 가장 많이 사용됩
- 운영체제와 사용자 사이에 인터페이스
- 도커 컨테이너 안에 접속
- cmd는 명령 프롬프트 창이지만, shell에서는 프로그래밍도 가능하다.
docker exec -it 컨테이너이름 bash
4) Mongo DB Manual
https://www.mongodb.com/docs/manual/crud/
5) Mongo DB 작업
- 로컬에 설치: 터미널에서 접속해서 사용
- 도커에 설치: bash shell에 접속해서 명령어를 실행
- 접속도구 사용: Compass나 Robe 3T와 같은 GUT Tool을 이용해서 작업 수행 가능
6) 구성요소
- 데이터베이스: 가장 큰 단위
- 컬렉션: 테이블의 개념, 미리 생성하거나 구조를 만들 필요 없음
- 도큐먼트: 하나의 데이터로 관계형 데이터베이스의 행의 개념
- 필드: 관계형 데이터베이스에서 열의 개념
- 인덱스: 데이터를 빠르게 접근하기 위한 객체
- 조인 없음!! 대신 Embedding이나 Linking의 개념을 가짐
- 데이터 안의 필드에 다른 데이터를 포함시킬 수 있음
- SEELCT문의 결과로, 관계형 데이터베이스는 Row의 집합을 리턴하지만,
Cursor를 반환한다.
7) CRUD
데이터 작업을 위한 Application - RDBMS
▼
Message Broker - Kafka
▼
데이터 읽기를 위한 Applilcation - NoSQL
데이터 삽입
db.컬렉션이름.insertOne({키:값, 키:값})
db.컬렉션이름.insertMany([{키:값, 키:값..},{키:값, 키:값...}..])
db.users.insertOne({"name":"park", "age":26})
db.users.insertOne({"nick":"kim", "height":170})
- 키는 문자열이고 값은 null, 숫자, 문자, 객체, 배열 boolean, 날짜 등이 가능
- 데이터를 삽입할 때 ObjectId라는 타입의 _id라는 키 값이 같이 삽입된다.
데이터 전체 확인
db.컬렉션이름.find({})
데이터베이스 생성 및 사용
use 데이터베이스이름;
switched to db 데이터베이스이름;
- 쓰면 만들어지는 것이 특징
현재 데이터베이스 확인
db;
데이터베이스 삭제
db.dropDatabase();
전체 데이터베이스 확인 - 데이터가 존재하는 것만 확인 가능
show dbs;
데이터 확인
db.DB이름.find({});
Capped Collection
- 일반 Collection과 다르게 정해진 크기를 초과하게 되면 자동으로 가장 오래된 데이터를 삭제하는 collection
- 디스크가 한정된 상황에서 로그 데이터나 분석 결과를 저장할 때 사용
View
- 데이터베이스 안에 쓸 수 는 없고 읽기만 가능한 데이터베이스 개체
- 뷰를 만들면 읽기 속도가 빨라지고 보안을 유지할 수 있다.
8) Thread
Program : 동일한 목적을 달성하기 위한 파일의 집합
Process : 실행 중인 프로그램
Thread
- 프로세스 안에서 자원을 할당에서 수행하는 작업 단위
- 혼자서 동작할 수 없고 항상 Process 내에 속해서 동작해야 한다.
- 함수를 그냥 실행하면 함수는 수행이 종료될 때까지 다른 함수를 수행하지 못하는데,
함수를 Thread로 실행하면 수행 중간에 다른 Thread를 실행하고 돌아올 수 있다. - 실제 일하는 것보다 왔다갔다 하는 불필요한 시간이 긴 걸 OverHead라고 한다.
python에서 사용
import time
#스레드를 만들지 않고 2개의 함수를 호출하면 20초
def threadEx(id):
for i in range(10):
print('id={0} -> {1}'.format(id, i))
time.sleep(1)
for i in range(2):
threadEx("{0}번 스레드".format(i))
import time, threading
def threadEx(id):
for i in range(10):
print('id={0} -> {1}'.format(id, i))
time.sleep(1)
for i in range(2):
id = ("{0}번 스레드".format(i))
th = threading.Thread(target=threadEx, args=(id, ))
th.start()
print("메인 종료")
- 스레드도 메인이다
asynchronous(비동기)
- 동기: 순서대로 하나씩 실행
- 비동기: 수행 중에도 다른 작업으로 제어권을 넘길 수 있는 것
- 스레드 프로그래밍과 유사하게 사용
- 스레드 프로그래밍에서 주의할 점
- 여러 개의 스레드에서 하나의 자원을 공유해서 수정할 때 문제: lock을 제외하면 이상한 결과가 출력
import time, threading
g_count = 0
class ThreadEx(threading.Thread):
def run(self):
global g_count
for i in range(10):
print("id={0} 증가하기 전 --> {1}".format(self.getName(), g_count))
g_count = g_count +1
time.sleep(1)
print("id={0} 증가하기 전 --> {1}".format(self.getName(), g_count))
time.sleep(1)
for i in range(2):
th = ThreadEx()
th.start()
9) Mongo DB에서의 멀티 스레드를 이용한 데이터 삽입
- name을 인덱스로 설정해서 유일무이하게 저장하도록 컬렉션을 생성
db.sample.createIndex({name:1}, {unique:true});
데이터 삽입
db.sample.insertOne({name:"adam"})
db.sample.insert([{name:"itstudy"}, {name:"adam"}, {name:"ggangpae"}])
MongoBulkWriteError: E11000 duplicate key error collection: test.sample index: name_1 dup key: { name: "adam" }
- adam이 중복되기에 에러
db.sample.find({})
{
_id: ObjectId('65af5043bd0803f0661363c7'),
name: 'adam'
}
{
_id: ObjectId('65af509dbd0803f0661363c8'),
name: 'itstudy'
}
- NoSQL은 싱글스레드 형태로 동작하기 떄문에 itStudy는 삽입이 되고 adam부터 삽입이 안됨
- 멀티 스레드를 이용해서 삽입하려면 ordered:false라는 옵션을 추가
db.sample.insert([{name:"itstudy"}, {name:"adam"}, {name:"ggangpae"}], {ordered:false})
MongoBulkWriteError: E11000 duplicate key error collection: test.sample index: name_1 dup key: { name: "itstudy" }
- 오류가 발생하지만 'ggangpae'까지 삽입된 걸 확인할 수 있다.
4. Python의 Exception Handling (예외 처리)
1) 오류의 종류
물리적 오류(Complie Error): 문법적인 오류
- 전체를 컴파일하고 실행하는 프로그램에서는 이 오류가 있으면 실행하지 않는다.
- 파이썬이나 자바스크립트의 경우는 괄호나 들여쓰기 오류를 제외하고 일단 실행되는 부분까지는 실행
- 물리적 오류는 코드를 수정해서 해결
논리적 오류: 알고리즘 오류
- 문법적인 오류는 없어서 실행이 잘 되는데 원하는 결과가 만들어지지 않는 경우
- 디버깅으로 해결 - 순차적으로 프로그램을 실행시키면서 메모리 값을 확인하거나, 부분적으로 폐쇄시키면서 문제를 파악한다.
예외(Exception): 문법적인 오류는 없지만 실행 중 에러가 발생하고 프로그래밍이 중단되는 현상
- 런타임 오류라 코드로 해결할 수 없는 경우
- 런타임 오류가 아니라서 코드로 해결할 수 있는 경우
단언(Assertion)
- 오류가 아닌데 강제로 예외를 발생시키는 것
2) 예외 처리 (Exception Handling)
목적
- 예외가 발생하더라도 계속 작업을 수행하기 위해
- 예외가 발생한 경우 로깅을 하기 위해
예외 발생
def ten_div(x : int) -> float:
return 10/x
print(ten_div(3))
print(ten_div(0))
print("메인 종료")
try:
예외가 발생할 가능성이 있는 코드
except:
예외가 발생했을 때 수행할 코드
def ten_div(x : int) -> float:
return 10/x
try:
print(ten_div(3))
print(ten_div(0))
except Exception as e:
print(e)
3.3333333333333335
division by zero
- 예외가 발생해도 프로그램이 중단되지 않음
- Exception as e: 예외 발생한 이유 알려줌
3) 예외 종류 별 처리
예외 처리 클래스 계층
https://docs.python.org/3/library/exceptions.html
예외를 별도로 처리: except절은 개수 제한이 없다.
ar = [10, 20, 30]
try:
print(ar[0])
print(ar[1])
print(ar[3])
except ZeroDivisionError as e:
print("0으로 나누는 예외 발생")
except IndexError as e:
print("인덱스 예외 발생")
10
20
인덱스 예외 발생
- 예외 처리에서 except는 위에서 순차적으로 확인해서 자신의 타입과 일치하는 구문을 만나면 처리하고 빠져나간다.
- 상위 클래스 타입의 참조형 변수에는 하위 클래스 타입의 인스턴스를 대입할 수 있다.
- 반대는 불가: 순서가 반대로 되면 Not Reachable Code가 만들어진다.
4) else와 finally
- except 아래에 절을 만들어서 예외가 발생하지 않은 경우게 수행할 로직을 작성할 수 있다.
- finally는 예외 발생 여부에 상관 없이 수행할 로직을 작성할 수 있다.
ar = [10, 20, 30]
try:
print(ar[0])
print(ar[1])
print(ar[3])
except ZeroDivisionError as e:
print("0으로 나누는 예외 발생")
except IndexError as e:
print("인덱스 예외 발생")
except Exception as e:
print()
else:
print("예외가 발생하지 않은 경우에 수행")
finally:
print("무조건 수행")
10
20
인덱스 예외 발생
무조건 수행
5) 강제로 예외 발생 - 단언
raise 예외클래스이름(예외 메시지)
try:
x = 10
if x < 20:
raise Exception("숫자가 너무 작음")
print(x)
except Exception as e:
print(e)
숫자가 너무 작음
5. Python과 Mongo DB 연동
1) 기본적인 사용법
패키지 설치
pip install pymongo
서버 연결
변수1 = pymongo.MongoClient("서버 IP", 포트번호)
데이터베이스 연결
변수2 = 변수1.데이터베이스 이름# 없으면 생성됨
컬렉션 연결
변수3 = 변수2.컬렉션이름 # 없으면 생성됨
데이터 1개 삽입
변수3.insert_one(dict 객체)
데이터 여러 개 저장
변수3.insert_many([dict 객체, dict 객체...])
from pymongo import MongoClient
#Mongo 데이터베이스 연결
con = MongoClient('127.0.0.1', 27017)
print(con)
#사용할 데이터베이스 연결
myDb = con.myDb
print(myDb)
#컬렉션 연결
col = myDb.col
print(col)
#1개 데이터 삽입
col.insert_one({'name':'kim', 'age':45})
#여러 개 데이터 삽입
col.insert_many([{'name':'lee', 'age':25}, {'name':'park', 'age':66}])
MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True)
Database(MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True), 'myDb')
Collection(Database(MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True), 'myDb'), 'col')
결과출력
result = col.find()
for row in result:
print(row['name'])
kim
lee
park
NoSQL은 COMMIT을 안한다. 기본적으로 Transaction이 제공되지 않는다. 읽기 위주로 하기 때문이다.
'SQL' 카테고리의 다른 글
JOIN (0) | 2024.01.23 |
---|---|
D3. 데이터 자료형 (0) | 2024.01.22 |
Transaction (1) | 2024.01.22 |
D2. SQL 문법 (1) | 2024.01.22 |
D1. 데이터베이스 개요 (1) | 2024.01.10 |