Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump shell-quote from 1.6.1 to 1.7.3 #10

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions _data/navigation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,12 @@ pop:
# - title: "with"
# url: /series/principles_of_python/
#
# - title: 고급 파이썬 문법
# children:
- title: 고급 파이썬 문법
children:
# - title: "데코레이터"
# url: /series/principles_of_python/decorator/
# - title: "프로퍼티"
# url: /docs/pages/
# - title: "async await"
# url: /series/principles_of_python/async_await/
- title: "async await"
url: /series/principles_of_python/async_await/

111 changes: 111 additions & 0 deletions _posts/2021-08-17-django-1-4-augmented-field.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
layout: single
title: "S3에 바로 올라가는 ORM 파일 필드 만들기"
date: 2021-08-07 11:10:03 +0900
categories: [Postgresql, MVCC]
---


## Environment
python 2.7.14
Django 1.4 (고대 쟝고)
South 1.0.2
기존 코드를


## 쟝고에 FileField 는 있는데 왜 S3FileField 는 없을까!!

기존 코드에서는 FileField 를 사용한 뒤, Form 의 save_new() 함수에서 s3 업로드를 진행한 뒤,
S3 경로의 FileField 의 url 을 바꿔치기 하는 방식을 사용하고 있었습니다.

이 방식을 사용했을 때

* 필드가 해야 할 일을 form 이 대신한다.
* column 만 봤을 때는 파일이 s3 에 올라가는지, 로컬(그럴리 없지만)에 저장되는지 알 수 없다.

라는 문제점이 남게 됩니다.

```python
# coding=utf-8
from datetime import datetime

from django.forms.models import BaseInlineFormSet
from util import upload_image_to_s3 # s3 에 파일을 업로드 하는 util 함수
from const import UPLOAD_DIRS # S3 버킷 안의 폴더

class ImageInlineFormset(BaseInlineFormSet):

def save_new(self, form, commit=True):
# 기타 여러가지 form set 이 하는 작업들 ...

# + S3 업로드 작업
obj = super(ImageInlineFormset, self).save_new(form, commit=False)
image = form.files.get(u'{}-image_url'.format(form.prefix))

if image:
filename = u'{:%Y%m%d%H%M%S%f}_{}'.format(
datetime.now(),
image.name,
)
s3_path = upload_image_to_s3(UPLOAD_DIRS, image, filename)
obj.image_url = s3_path

if commit:
obj.save()

return obj
```


## S3FileField
그래서 S3FileField 를 만들었습니다~

```python
from datetime import datetime

from django.db.models import FileField
from south.modelsinspector import add_introspection_rules

from utils import upload_image_to_s3


class S3FileField(FileField):

def __init__(self, *args, **kwargs):
super(S3FileField, self).__init__(*args, **kwargs)

def _upload_to_s3(self, image):
filename = u'{:%Y%m%d%H%M%S%f}_{}'.format(
datetime.now(),
image.name,
)
return upload_image_to_s3(self.upload_to, image, filename)

def pre_save(self, model_instance, add):
file = super(FileField, self).pre_save(model_instance, add)
if file and not file._committed:
file.name = self._upload_to_s3(file)
return file


add_introspection_rules([], ["^dowant\.promotion\.fields\.S3FileField"])

```

* pre_save() 를 override 합니다. 여기서 s3 에 업로드 합니다.
* add_introspection_rules 를 추가해야 마이그레이션 파일이 만들어집니다.


## 사용
필드를 만든 후에는 일반 FileField 처럼 사용하면 됩니다.
```python
image = S3FileField(
max_length=300,
upload_to='s3-버킷-안의-폴더/',
storage=FileSystemStorage(location='', base_url='https://s3-bucket-경로'),
)
```




104 changes: 104 additions & 0 deletions _posts/2021-09-19-mysql_char_varchar_text.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
layout: single
title: "Mysql Char vs Varchar vs TEXT 언제 쓰는게 좋을까?"
date: 2021-09-19 11:10:03 +0900
categories: [Mysql]
---

# Char vs Varchar vs TEXT
언제 쓰는게 좋을까? 직접 테스트 해봤습니다.

# TL; DR

* (mysql8, utfmb4 에서...) 16000자 이하: varchar < 65535자 이하: TEXT (CHAR 는 왜 쓰는지 모르겠음)
* char 가 varchar 보다 성능이 좋다는 얘기가 있는데, 테스트 해봤을 때 유의미한 차이는 없었습니다.
* varchar 는 저장 공간이 가변이라 disk 낭비가 적으며, index도 됩니다.
* TEXT 는 index 도 안되고 default 값도 안 됩니다만 (^__^) varchar 보다 많이 저장할 수 있습니다.


# Char
* 고정 길이
* 0~255 까지의 길이를 지정할 수 있습니다. (byte 가 아니라 길이)
* 고정 길이 만큼의 disk space 를 차지합니다.
* CHAR(10) 에 'abcd' 를 저장하면, 'abcd' 와 함께 빈 6자리를 채우기 위해 6개의 space (padding) 가 뒤에 채워집니다.
* 채워진 스페이스는 해당 row 를 가져올 때 빼고 가져옵니다.
* PAD_CHAR_TO_FULL_LENGTH 설정이 켜져 있다면 빼지 않고 스페이스도 가져옵니다.
* index 가능

# Varchar
* 저장된 문자열 만큼의 disk space 만 차지합니다.
* Char 와 다르게 prefix byte 를 사용합니다. (1~2 byte 남짓을 추가적으로 사용)
* 최대 65535 byte 를 저장합니다. (길이가 아니라 byte) 어떤 character set 을 사용하느냐에 따라 max 길이가 달라집니다.
* 테스트 해보니 (약)16000자가 최대였습니다. (mysql 8.0.25에서 utfmb4 charset 사용)
* index 가능

# Text
* varchar 보다 더 큰 값을 가질 수 있습니다.
* index 불가
* default 값을 가질 수 없습니다. (눈물)
* 테스트 해보니 65535 자를 (길이) 저장할 수 있었습니다. (mysql 8.0.25에서 utfmb4 charset 사용)
* stack overflow 에서 65535 byte 를 저장한다는 글을 많이 볼 수 있었는데, 사실은 byte 가 아니라 글자 수가 65535자 입니다.


# VARCHAR 와 Text 길이 테스트
* python 으로 고정 길이의 문자열을 만듭니다. `'a' * 16125`
* utf8mb4 에서 어떨 때는 16125 보다 긴 컬럼으로 ALTER 할 때 에러 발생, 어떨 때는 16179 보다 길 때 에러 발생... 정확한 기준을 모르겠습니다.
* varchar(16125) 의 경우 정말 `'a' * 16125` 는 할당되지만 `'a' * 16126` 는 할당 안 됬습니다.


# CHAR VS VARCHAR 테스트
애초에 CHAR 의 최대 길이가 255 입니다. 이렇게 작은 값을 read 해 올 때 성능 비교는 의미가 없는 것 같습니다.
500 row 이상을 한 번에 불러오는 경우도 생각해 볼 수 있겠으나... 이건 성능의 문제보다는 pagination 을 안해서
생기는 문제라고 생각합니다.
* CHAR(200) 과 VARCHAR(200) 을 컬럼을 만듭니다.
```
create table string_table
(
my_char char(200) null,
my_varchar varchar(16179) null,
my_text text null,
id int auto_increment
primary key
);
```
* my_char 에 'a' 200 개로 이루어진 문자열을 저장한 컬럼 250개 생성
* my_carchar 에도 'a' 200 개로 이루어진 문자열을 저장한 컬럼 250개 생성
* 두 쿼리의 성능 비교
* `SELECT my_char FROM string_table WHERE my_char IS NOT NULL;`
* `SELECT my_varchar FROM string_table WHERE my_varchar IS NOT NULL;`

```
> SELECT my_char FROM string_table WHERE my_char IS NOT NULL
[2021-09-18 23:07:11] 250 rows retrieved starting from 1 in 48 ms (execution: 8 ms, fetching: 40 ms)
> SELECT my_char FROM string_table WHERE my_char IS NOT NULL
[2021-09-18 23:07:36] 250 rows retrieved starting from 1 in 77 ms (execution: 8 ms, fetching: 69 ms)
> SELECT my_char FROM string_table WHERE my_char IS NOT NULL
[2021-09-18 23:07:37] 250 rows retrieved starting from 1 in 70 ms (execution: 9 ms, fetching: 61 ms)
> SELECT my_char FROM string_table WHERE my_char IS NOT NULL
[2021-09-18 23:07:38] 250 rows retrieved starting from 1 in 59 ms (execution: 9 ms, fetching: 50 ms)
> SELECT my_varchar FROM string_table WHERE my_varchar IS NOT NULL
[2021-09-18 23:07:51] 252 rows retrieved starting from 1 in 57 ms (execution: 10 ms, fetching: 47 ms)
> SELECT my_varchar FROM string_table WHERE my_varchar IS NOT NULL
[2021-09-18 23:07:52] 252 rows retrieved starting from 1 in 60 ms (execution: 8 ms, fetching: 52 ms)
> SELECT my_varchar FROM string_table WHERE my_varchar IS NOT NULL
[2021-09-18 23:07:53] 252 rows retrieved starting from 1 in 51 ms (execution: 9 ms, fetching: 42 ms)
> SELECT my_varchar FROM string_table WHERE my_varchar IS NOT NULL
[2021-09-18 23:07:54] 252 rows retrieved starting from 1 in 53 ms (execution: 9 ms, fetching: 44 ms)
> SELECT my_varchar FROM string_table WHERE my_varchar IS NOT NULL
[2021-09-18 23:07:54] 252 rows retrieved starting from 1 in 63 ms (execution: 9 ms, fetching: 54 ms)
```

결론: `또이또이`

# Reference

https://stackoverflow.com/questions/25300821/difference-between-varchar-and-text-in-mysql/25301046#25301046

https://dev.mysql.com/doc/refman/8.0/en/char.html







Loading