이런 여러개의 저장장치가 동시에 사용되어 서로 교류하면서 저장이 이루어짐. 밑으로 내려갈 수록 저장용룡이 커지고, 위로 올라갈수록 속도가 빨라지고 가격이 비싸짐. 레지스터는 CPU에 붙어있는 아주 소규모, 고속의 장치. 레지스터가 조금 늘어나는것 만으로도 CPU의 가격이 2~30배 뛸 수 있다. 그렇기에 레지스터로 모든 저장을 처리할 수가 없어 접근 속도는 떨어지지만 용량은 크고 가격은 저렴한 아래쪽까지 사용한다.
비휘발성은 저장 장치는 너무 느려 한번 저장하고 간간히 읽는데 사용하는 정도로만 사용한다. 읽고 쓰는데 적합한 저장장치들이 아니다. 그나마 읽고 쓰는데 쓸만한 장치는 플래쉬 메모리, 자기 디스크 정도. 그렇더라도 메인 메모리에 비해 1000배는 느리다. 휘발적이나 캐시, 메인 메모리가 정말 빠르게 작동하고 있음을 알 수 있다.
하나의 데이터베이스는 큰 하나의 데이터 집합으로 보이나, 데이터 저장을 위해 운영장치가 제공하는 데이터 저장 구조의 가장 낮은 단계인 "파일"단위로 운영된다. DBMS가 운영체제에 맞는 파일구조로 데이터를 가지고 있는 것. 이 파일이 다시 작은 단위로 나뉜게 "블럭". 하나의 파일은 디스크에 저장될 때 여러개의 블럭 단위로 분리되어 저장되며, 하나의 블럭에는 여러개의 "레코드"를 보유한다.
하나의 블럭에 데이터는 어떻게 저장될까? 하나의 릴레이션의 레코드는 모든 레코드의 길이가 동일한게 있고, 레코드별로 길이가 들쭉날쭉한 릴레이션이 있음
INT(4) 다 더하면 42. 모든 레코드는 42정도의 길이를 유지하고 있음.
고정 길이 레코드를 저장하려면 어떻게 하면 될까? 레코드의 길이가 일정하므로 차곡차곡 쌓을 수 있음.
내가 두번째 레코드를 읽고 싶으면 어떻게 하면 될까? 고정 길이이므로, 43~84까지 읽으면 됨.
블럭에 k개 차곡차곡 집어넣고 있다가, 조금 남은거는 어쩌지? 42바이트는 안돼서 레코드 하나 더 못넣음. 그럼 다음레코드부터는 다른 블럭에 넣어야 함. 따라서 모든 블럭에 42바이트보다 작은 잔여공간이 낭비되고 있음. 블럭의 갯수가 많으면 낭비되는 공간이 꽤 됨.
아.. 이거 버려지는거 너무 아깝다. 이거 좀 바꿔보자! 해서 나온 게 이것
되는데까지 다 채워서 넣고, 남은거 조금 다음거에 넣음. 30남으면, 30까지 넣고 나머지 12를 다음 블럭에 저장. 문제는, 정보를 출력할때 두개의 블럭에 걸쳐있는 레코드를 가져올때, 두개의 블럭을 가져와야 해서 속도가 매우 느려질 수 있다.
뿐만 아니라 추가적으로 더 많은 문제가 발생 가능. 중간중간 레코드를 삭제하면 다시 레코드 삽입할 때 빈공간에다 레코드 넣으면 좋지 않을까? 그런데 컴퓨터가 빈칸이 어디있는지 어떻게 알지? 삭제 위치를 몰라 뒤에 막 추가하면 삭제된 레코드의 저장공간은 그냥 비워진채로 낭비되게 된다.
레코드 삭제 시
레코드 삭제 시 대처 방안
공백 레코드 포인트가 빈공간의 링크를 가지고 있음. 빈공간이 어디있는지 링크를 따라가면 다 알 수 있음. 새로운 데이터가 추가 되는 경우 링크 순서대로 가용 리스트를 하나씩 따라가며 데이터를 매꿔감.
실제 현장에서도 가용 리스트를 가장 많이 사용한다!
멀티셋: 레코드의 컬럼값이 여러 개인 컬럼
(컬럼값의 원자성을 확대한 멀티셋을 제공한 DBMS가 종종 있음)
하나의 레코드를 정의하는 방법이 달라짐.
가장 첫번째 들어오는 값: 4byte를 소모하면서, 여기에 가변길이컬럼이 있는데 몇번째 바이트부터 시작하고, 길이는 얼마나 되는지 알려줌.
이후 고정길이 값들이 쭉 들어가고, NULL이 들어감.
NULL의 의미: 여기까지 고정길이 값들이 끝났어, 여기부터는 가변길이 값이야!
27번에서 6byte 크기의 가변데이터가 들어갈거야!
26byte에 NULL이 입력되어 이후 가변길이데이터가 들어감을 알려줌
한 블럭에서 이러한 가변길이 레코드를 어떻게 저장해야 할까?
-> "슬롯페이지 구조"를 대표적으로 많이 사용한다.
하나의 릴레이션은 여러개의 블럭으로 나뉘어 저장된다. 만약 해당 릴레이션에 손흥민이라는 새로운 데이터가 추가될 때, 어느 블럭에 추가되면 될까? 마지막 블럭의 마지막 칸에? 기존 데이터가 삭제된 빈칸에? 새로운 신규 데이터가 어느 장소에 저장될지에 대한 기준, 방법이 규정되어야 한다. 이같은 방법에 3가지 종류가 있다.
힙구조: 저장순서 고려 없이 파일 내 임의의 위치에 배치
근처 아무데나 자리 있으면 무작위로 거기다 넣어줘.
=> 저장속도는 가장 빠름. but 저장위치를 모르므로 사용의 효율은 가장 떨어짐
순차 파일 구조: 레코드들이 탐색키 기준으로 정렬되어 저장
나 새로은 정보는 사번에 맞춰서 넣을거야. 사번이 제일 늦으니까, 제일 마지막 자리로 들어가.
=> 순서를 고려하므로 저장속도는 느림. but, 이진탐색트리를 통한 사번 검색으로 탐색 속도를 줄일 수 있음.
해시파일구조: 해시 함수를 사용하여 블럭 주소를 계산
_탐색키가 사번이라면, 사번을 어느 블랙박스에 넣어서 나온 숫자에 넣어둠. 다시 해당 레코드를 찾고 싶으면, 사번을 블랙박스에 넣어서 저장 위치를 알 수 있음. 일종의 번호생성기를 활용.
해쉬파일의 번호사용기의 성능에 따라 속도차가 크므로, 실제로는 순차 파일구조가 가장 빈번히 활용됨.
맨끝에 가용레코드와 유사하게 다음 레코드를 연결해뒀음. 그래서 만약 "안창호"데이터를 보면, 그 다음 데이터를 링크를 통해서 따라갈 수 있게 해놓음. but, 만약 새로운 데이터가 추가되면 이 링크 체인을 유지하기 위해 추가 작업이 필요함.
저장 방식을 개선하기 위해 사용한다.
1. 순차 파일 구조에서 레코드의 정렬된 상태 유지를 위해 삽입된 신규 블럭
손흥민 데이터를 순서대로 넣기 위해서는, 안창호 부터 밑으로 쫙 내려서 칸을 만들고 거기에 넣어야함. 이게 너무 많은 과정을 요구하므로, 아예 나철수가 손흥민을 가르키도록 변경함. 순서대로 접근 시 두개의 블럭에 접근해야 하는 단점이 있으나, 저장 속도를 획기적으로 줄여줄 수 있음
디스크는 느리니까 접근을 최소화하고 한번 읽은 블럭을 여러번 재사용하도록 만드는 것이 컴퓨터 속도 향상에 가장 효과적이다.
디스크에 저장되어있는 영구적 데이터가 존재하고, 소프트웨어는 이 저장공간에 다양한 질문을 하게 된다. 이때 소프트웨어는, 먼저 운영체제위의 DBMS가 관리하는 메모리에서 먼저 답변이 있는지 확인하고 있으면 바로 답변하고, 없으면 디스크로 가서 메모리에 필요한 정보를 적재하고 이 데이터를 통해 답변한다.
필요한 데이터를 가지고 오는 역할, 메모리가 꽉 찼을때 다시 디스크로 내보내고 추가로 가져올 데이터를 가져오는 것을 "버퍼관리자"가 수행한다.
단기기억, 장기기억 느낌이다. 나는... 컴퓨터가 아닐까..?
디스크의 하나의 블럭을 가져오는데 빈공간이 없으면 있는걸 내보낸다고 했다. 그럼.. 내보내는 기준이 뭘까?
그냥 아무거나 내보내면 안될까요? 안됩니다. 방금 내보낸 데이터를 또다른 사용자가 또 요구한다면? 방금 내보낸 데이터를 다시 꺼내와야함. 어마어마한 자원적, 시간적 낭비가 일어날 수 있다. 따라서, 가장 안쓰일거 같은 데이터를 내보내야 함.
정답이 없는 문제. 어떤게 가장 적절할지는 개발자가 판단해야
때로는 DBMS의 버퍼관리자를 통하지 않고, 사람이 강제적으로 정보를 넣거나, 넣는것을 막는 기능이 필요할 수 있음.
고정 블럭: 데이터 처리중이라 임시값이 들어가 있거나, 프로그램에 오류에 의해 잘못된 값이 들어가 있는 경우 이 같은 데이터들이 DB에 입력되지 않도록 막아야 함.
블럭 강제 출력: 반대로, 버퍼교체 전략에 의해 선택될거 같지 않지만, 운영체제나 서버, DBMS 등의 오류로 셧다운이 될 수 있음. 이런 경우 중요 기록이 소실되기전 빠르게 영구저장 장치로 저장하는 기능이 필요할 수 있음.
시스템 로그와 같이 중요한 데이터는 디스크에 영구적으로 기록되어야 함
버퍼 공간이 필요 없어도 강제로 디스크에 기록
놈놈 재뮛다 ㅎㅎ