NoSQL

0ㅑ채
|2024. 1. 23. 17:45

 

 

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/

 

MongoDB CRUD Operations — MongoDB Manual

Docs Home → MongoDB Manual CRUD operations create, read, update, and delete documents.You can connect with driver methods and perform CRUD operations for deployments hosted in the following environments:Create or insert operations add new documents to a

www.mongodb.com

 

 

5) Mongo DB 작업

  • 로컬에 설치: 터미널에서 접속해서 사용
  • 도커에 설치:  bash shell에 접속해서 명령어를 실행
  • 접속도구 사용: Compass나 Robe 3T와 같은 GUT Tool을 이용해서 작업 수행 가능 

Connect만 하면 생김

 

 

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

 

Built-in Exceptions

In Python, all exceptions must be instances of a class that derives from BaseException. In a try statement with an except clause that mentions a particular class, that clause also handles any excep...

docs.python.org

 

예외를 별도로 처리: 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