데이터 중심 어플리케이션 설계 - 데이터모델과 질의 언어
관계형 데이터 모델
- 데이터는 테이블이라는 관계로 구성되고 순서가 없는 튜플(Tuple)의 형태 (로우의 모음 row)
- 질의 최적화기 (Optimizer) : 어떤 순서로 실행할지를 결정하고 사용할 색인을 자동 결정한다.
- 다대일, 다대다 관계표현 : 외레키
정규화: 데이터의 중복을 없애는 것
회사정보 테이블
company_id | company_name | company_type | company_number | reg_date |
---|---|---|---|---|
101 | (주)운송물류 | 물류 | 12353512 | 2024-08-10 13:00:00 |
102 | (주)교통 | 전기버스 | 12335642 | 2024-05-20 15:15:27 |
차량정보 테이블
car_id | comapny_id | car_number | car_type | driver_id | reg_date |
---|---|---|---|---|---|
1100 | 101 | 차량12가3069 | 버스 | 10 | 2024-09-20 13:13:20 |
1102 | 101 | 차량12바2019 | 물류 | 2 | 2024-08-12 13:25:20 |
1103 | 102 | 차량12가3208 | 전기버스 | 8 | 2024-09-20 15:30:20 |
운행기록 테이블
car_id | company_id | speed | start_date | end_date | latitude | longitude |
---|---|---|---|---|---|---|
1100 | 101 | 80 | 2024-08-05 12:25:35 | 2024-08-05 12:25:36 | 127.12 | 234.45 |
1100 | 101 | 80 | 2024-08-05 12:25:36 | 2024-08-05 12:25:37 | 127.12 | 234.45 |
1102 | 102 | 45 | 2024-08-10 14:25:36 | 2024-08-10 14:25:37 | 127.24 | 234.55 |
1102 | 102 | 45 | 2024-08-10 14:25:37 | 2024-08-10 14:25:38 | 127.24 | 234.55 |
SELECT company.company_name as company_name, car.car_no as car_no, history.drive_record
FROM company company, car car, drive_history history
WHERE company.company_id = car.company_id
AND car.car_id = history.car_id;
문서형 데이터모델
- 대규모 데이터 셋이나 쓰기 처리율이 높은 것들에 대해 최적화 되어 있음
- 스키마가 존재하지 않기 때문에 유연함
- 모든 관련 정보가 한 곳에 중앙집중화되어 있기 때문에 한 번의 질의 조회로 충분
스키마: 데이터가 어떤식으로 저장이 되는지에 대한 데이터 구조
{
"_id" : "66f82a1a62afc70d7a072f8a",
"company_id" : 101,
"driver_history" : [
{
"speed" : 80,
"start_date" : "2024-08-05T12:25:35Z",
"end_date" : "2024-08-05T12:25:36Z",
"latitude" : 127.15,
"longitude" : 234.34,
"gaspedal" : 35,
"azimuth" : 330
},
{
"speed" : 80,
"start_date" : "2024-08-09T13:25:35Z",
"end_date" : "2024-08-09T13:25:36Z",
"latitude" : 127.15,
"longitude" : 234.34,
"gaspedal" : 35,
"azimuth" : 330
},
// 운행기록데이터
]
}
그래프형 데이터 모델
데이터간 연결관계가 복잡할 경우 그래프 데이터 모델링하는 것이 자연스러움
예시: 페이스북이나 linked in처럼 사람들 간의 관계를 표현하는 방식, 사기 탐지, 경로 최적화 등
- 정점 (vertex): 노드, 엔티티
- 간선 (edge): 관계, 호
데이터를 위한 질의 언어
명령형
특정 순서로 특정 연산을 수행하게끔 컴퓨터에게 지시함
def getShark(animals):
sharks = []
for animal in animals:
if animal == 'Sharks':
sharks.append(animal)
return sharks
const liElements = document.getElementsByTagName("li");
for (let i = 0; i < liElements.length; i++) {
if (liElements[i].className === 'selected') {
let children = liElements[i].childNodes;
for (let j = 0; j < children.length; j++) {
let child = children[j];
if (child.nodeType === Node.ELEMET_NODE && child.tagName === 'P') {
child.setAttribute('style', 'background-color: blue');
}
}
}
}
선언형
방법이 아닌 알고자하는 데이터의 패턴 - 어떤 순서로 특정 연산을 수행하지는 최적화도구등이 결정
SELECT animals_nic_name, animals_shape
FROM animals
WHERE family = 'Sharks';
li.selected > p {
background-color: blue;
}
맵리듀스 질의
- 대량의 데이터를 처리하기 위한 프로그래밍 모델
- 많은 문서를 대상으로 읽기 전용 질의를 수행할 때 사용
- 함수형 프로그래밍의
map
,reduce
함수와 유사
db.observations.mapReduce(
function map() {
var year = this.observationTimestamp.getFullYear();
var month = this.observationTimestamp.getMonth() + 1;
emit(year + "-" + month);
},
function reduce(key, values) {
return Arrays.sum(values);
},
{
query : { family : "Sharks" },
out : "monthlySharkReport"
}
)
db.monthlySharkReport.find().pretty();
Aggregate
맵리듀스의 사용자 정의 함수를 정의하지 않고도, 맵-리듀스 로직 작성 가능
db.observations.aggregate([
{ $match: { family: "Sharks" } },
{ $group: {
_id: {
year: { $year: "$observationTimestamp" },
month: { $month: "$observationTimestamp" }
},
totalAnimals: { $sum: "$numAnimals" }
} }
])
댓글남기기