#title Delete와 Update의 내부동작 [[TableOfContents]] Delete시 MSSQL Server는 Delete된 행을 지웠다는 표시만 한다. 그러므로 데이터를 읽을 때는 Delete된 행의 표시가 있으므로 읽지 않는다. 이것은 클러스터드 인덱스나 논클러스터드 인덱스의 리프레벨에서 모두 일어난다. 만약 힙(Heap)이라면 Delete된 행은 빈공간이나 마찬가지지만 실제로는 빈공간이 아니므로 압축될 수 없다. 그러나 무한정 압축하지 않는 것은 아니다. 새로운 행을 삽입하기 위한 공간이 부족하다면 그제서야 압축을 한다. 데이터페이지에서 마지막 행이 삭제되면 전체페이지가 할당해제(DeAllocate)한다. 물론 MSSQL Server는 테이블당 적어도 하나의 페이지를 가지고 있어야 하므로 1페이지만 있을 경우는 할당해제를 하지 않는다. Update의 경우는 실제 많은 작업이 일어난다. 만약 데이터행이 포함된 페이지에 Update한 데이터가 들어가지 못할 경우는 전체 행을 다른 페이지로 옮긴다. 또한 클러스터드 인덱스가 걸려 있다면 인덱스 키의 순서를 조정하기 위해서 다른 페이지로 데이터 행이 옮길 수 있다. 물론 이때는 논클러스터드 인덱스의 리프노드가 클러스터드 인덱스의 키값을 가리키고 있으므로 논클러스터드 인덱스의 리프노드도 변경된다. 이러한 것을 행마이그레이션이라고 한다. 그러므로 클러스터드 인덱스는 웬만하면 변경이 일어나지 않는 컬럼(들)에 생성하는 것이 좋다. 만약 데이터의 일부를 기존페이지에 남겨두고 나머지를 다른 페이지에 둔다면 행체인이 일어난다. 그러면 실제 하나의 행을 접근하기 위해서 2개의 페이지에 접근해야 하므로 I/O비용이 상승하기 때문에 이러한 방식은 이제 사용하지 않는다. 만약 Heap에서 위와 같이 갱신작업이 일어나면 논클러스터드 인덱스는 실제 데이터 행의 물리적 위치를 가리키는 포인터를 가진다. 그러므로 논클러스터드 인덱스는 변경할 필요가 없다. 왜냐하면 논클러스터드 인덱스는 변경전의 데이터행의 위치를 가리키고 있기 때문이다. 그런데도 데이터를 정확히 가져올 수 있는 것은 원래의 데이터행의 위치로 이동하면 그곳에는 새로운 데이터행의 위치를 가리키는 포인터가 있기 때문이다. 물론 행마이그레이션이 일어나지 않아도 되는 크기로 다시 변경된다면 원래 위치로 다시 이동된다. 그러므로 역시 논클러스터드 인덱스는 변경되지 않아도 된다. 실제로 말은 좋아보이지만 MSSQL Server의 최소 입출력 단위는 페이지이기 때문에 페이지 단위로 입출력이 일어나면 더 많은 페이지를 읽을 수 있다는 말도 된다. 그러므로 관리자는 인덱스를 재생성 또는 조각모음을 주기적으로 해주어야 한다. 참고적으로 알아두어야 할 것은 DBCC INDEXDEFRAG 는 인덱스는 조각모음이 가능하지만 Heap은 조각모음이 되지 않는다. 그러므로 클러스터드 인덱스를 생성하는 것은 MSSQL Server 아주 중요한 의미를 가진다. Point Query 위주라면 오히려 인덱스 재생성 또는 조각모음으로 인한 부하가 더 생길 수도 있다.