Django - ORM 과 SQL
ORM
많이 늦은 감이 있지만, 우선 ORM에 대해서 한번 정의하도록 하자.
ORM이란?
- Object Relational Mapping 의 약자로 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결) 해주는 것을 말한다.
- 객체 지향 프로그래밍은은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다.
- 객체 모델과 관계형 모델 간에 불일치가 존재하는데, ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결한다.
- 데이터베이스 데이터 <-매핑-> Object 필드
- 객체를 통해 간접적으로 데이터베이스 데이터를 다룬다.
SQL
SQL은 데이터베이스에 정리해 놓았다. 해당 내용을 확인하자.
작동문
SQL, ORM 형식으로 간단히 정리해보자.
SQL을 학습하면서 설정한 ERD는 아래와 같다.
이를 Djagno의 object로 표현하면 아래와 같다.
class Artist(models.Model):
id = models.BigAutoField(auto_create=True, primary_key=True, verbose_name='ID')
name = models.CharField(max_length=100)
class Meta:
db_table = 'artists'
class Song(models.Model):
id = models.BigAutoField(auto_create=True, primary_key=True, verbose_name='ID')
title = models.CharField(max_length=100)
artist = models.ForeignKey(User, on_delete=models.CASCADE)
lyrics = models.CharField(max_length=2000, null=True)
class Meta:
db_table = 'songs'
SQL의 CREATE문 부터 시작하자.
CREATE TABLE artists(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
PRIMARY KEY (id));
CREATE TABLE songs(
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(100) NOT NULL,
artist_id INT NOT NULL,
lyrics VARCHAR(100),
PRIMARY KEY (id),
FOREIGN KEY (artist_id) REFERENCES artists (id));
artists 테이블에 아이유를 가수로 생성해주자. 그 후에 song테이블에 낙하와 밤편지라는 음반을 넣어주자.
# SQL
INSERT INTO artists(name) VALUES ('아이유');
INSERT INTO songs(title, artist_id) VALUES('낙하', 1);
INSERT INTO songs(title, artist_id) VALUES('밤편지', 1);
# ORM
Artist.objects.create(name = '아이유')
Song.objects.create(title = '낙하', artist_id = 1)
Song.objects.create(title = '밤편지', artist_id = 1)
만일, 아이유가 만든 음반을 전부 알고 싶다면 아래처럼 작성해보자.
# SQL
SELECT * FROM songs WHERE songs.artist_id = 1;
# ORM
Song.objects.filter(artist_id = 1)
만약, songs 가 아니라 artists에서 시작한다면? 거기에 음반 title만 알고싶다면?
# SQL
SELECT songs.title FROM artists JOIN songs ON artists.id = songs.artist_id WHERE artists.name ='아이유';
#ORM
songs = Artist.object.get(name = '아이유').song_set.all()
for song in songs:
print(song.title)
이렇게만 보면 바로바로 1:1 매칭이 되는 것 같지만..실제로 ORM으로 코드를 작성한다면 쿼리를 수도없이 난발할 수 있다.
예를 들어 음반가격이라는 테이블을 추가로 설정해주고, 해당 내용을 불러온다고 가정하자.
#SQL
CREATE TABLE song_price(
id INT NOT NULL AUTO_INCREMENT,
price INT NOT NULL,
song_id INT NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (song_id) REFERENCES songs (id));
#ORM
class SongPrice(models.Model):
id = models.BigAutoField(auto_create=True, primary_key=True, verbose_name='ID')
price = models.CharField(max_length=100)
song = models.ForeignKey(Song, on_delete=models.CASCADE)
class Meta:
db_table = 'song_price'
이후 price 테이블에 음반마다 가격을 정해주자.
# SQL
INSERT INTO song_price(price, song_id) VALUES (25000, song_id = 1);
INSERT INTO song_price(price, song_id) VALUES (30000, song_id = 1);
# ORM
SongPrice.objects.create(price = 25000, song_id = 1)
SongPrice.objects.create(price = 30000, song_id = 2)
그런 후, 아이유의 음반과 해당하는 가격까지 함께 출력해준다면? 아마 아래처럼 작생해볼 수 있을 것이다.
#SQL
SELECT * FROM artists LEFT JOIN songs ON artists.id = songs.artist_id JOIN song_price ON songs.id = song_price_id WHERE artists.name ='아이유
#ORM
artist = Artist.objects.get(name = '아이유')
songs = artist.song_set.all()
song_list = []
song_information = {}
for song in songs:
for price in song.songprice_set.all():
song_information['title'] = song.title
song_information['price'] = price.price
song_list.append(song_information)
print(song_list)
근데 ORM을 저렇게 작성하면, SQL의 쿼리는 최소한 3개는 날라갈 것이다. 이럴 때 필요한게 eager loading 개념이다.
중간 결론
ORM은 결국 SQL문을 직접 작성하지 않고 데이터베이스를 활용할 수 있게 도와주는 매개체이다.
잘못사용하면 SQL을 직접 사용하는 것보다 더 비효율성이 높아질 수 있으니 고민을 많이 해서 작성해야 한다.
Author And Source
이 문제에 관하여(Django - ORM 과 SQL), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@holyja/Django-ORM-과-SQL저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)