이 페이지는 기계 번역되었습니다. 영어 원본을 읽어보세요. English

IBSurgeon 라이브러리

VARCHAR와 INTEGER 필드의 키에서의 차이점

저는 테이블의 기본 키로 정수 ID를 사용하고 있습니다. 대신 varchar 필드를 사용하면 어떻게 될까요? 특히 큰 테이블에서 성능이 저하될까요? 조인은 정수 컬럼만큼 빠르게 작동할까요?

varchar나 정수를 사용하든 성능은 거의 동일해야 합니다. Firebird는 항상 인덱스 키를 바이트 단위로 비교하며 값의 중요한 부분만 저장됩니다.

단일 필드 키는 먼저 세 가지 표준 유형 중 하나로 변환됩니다: 콜레이션을 가진 문자열, 배정밀도(double precision), 그리고 (안타깝게도) 64비트 정수. 날짜는 배정밀도 부동소수점 숫자가 됩니다.

바이트 값과 다른 콜레이션을 가진 문자열은 해당 콜레이션 형식으로 변환됩니다. 이것은 일종의 난해한 기술이며 문자열의 크기를 확장하지만, 결과적으로 동일한 콜레이션을 가진 다른 문자열과 정렬될 때 올바른 위치를 찾게 됩니다. ‘A’, ‘a’, ‘â’, ‘á’, ‘Ă’, ‘ã’, ‘ä’, ‘å’, ‘ă’, ‘ą’, ‘Ā’ 모두 지정된 위치에 나타납니다. (이메일 클라이언트에 어떤 영향을 미쳤는지 사과드립니다…. 제 클라이언트에서는 ‘A’의 11가지 변형입니다.) 끝의 공백은 키에 포함되지 않습니다.

배정밀도 숫자는 바이트 단위로 정렬되도록 변환됩니다 - 대략 부호, 지수, 가수를 반전시키고 끝의 0을 잘라냅니다.

컴퓨터의 64비트 정수 엔디언에 따라 이들도 바이트 단위로 비교되도록 변환됩니다. 이는 비최적화처럼 보일 수 있지만, 인덱스 키는 자연 경계에 저장되지 않고 접두사 압축을 거치므로 바이트 단위보다 큰 비교를 사용할 방법이 없습니다.

복합 키도 거의 동일합니다. 각 부분은 인덱스 키 유형으로 변환되고 4바이트의 배수로 패딩됩니다. 4바이트마다 Firebird는 현재 키 필드의 위치를 나타내는 바이트를 추가합니다. 따라서 LastName, FirstName, ZodiacSign에 대한 인덱스는 1Harr1ison2Ann 3Gemi3ni로 나옵니다. 이렇게 하면 Damnation과 Dam nation을 혼동하는 문제를 피할 수 있습니다.

왜 위에서 “(안타깝게도)“라고 말했을까요? 숫자에 단일 형식이 있으면 Firebird가 인덱스를 다시 생성하지 않고 숫자의 크기를 변경할 수 있기 때문입니다. 그러나 Borland가 64비트 정수를 다시 추가했을 때 - InterBase는 Vax에서 처음부터 64비트 정수를 가지고 있었습니다 - 어떤 똑똑한 사람이 배정밀도는 56비트의 정밀도를 가지고 있고 64비트 정수는 64비트를 가진다는 것을 깨달았습니다. 반면에 Firebird 인덱스는 약간의 부정확성을 처리하도록 설계되었습니다… 또는 나머지 8비트를 끝에 붙일 수도 있었습니다… 어쨌든. 그래서 Numeric/Decimal 9에서 Numeric/Decimal 12로 변경할 때 인덱스를 다시 구축해야 합니다. 안타깝습니다.

“접두사 압축?” 페이지의 첫 번째 키나 점프 후 첫 번째 키가 아닌 키를 저장할 때 Firebird는 이전 키를 살펴보고 다음 키의 시작 부분에서 이전 키와 중복되는 부분을 잘라내고 잘라낸 부분의 길이를 시작 부분에 붙입니다. 따라서 문자열 “AAAA”, “AAAB”, “AAAC”, “AABC"는 다음과 같이 됩니다:

“AAAA”, “3B”, “3C”, “2BC”. 숫자의 가변 부분이 먼저 오고 고정 부분이 뒤에 오는 일부 GUID 형식에는 문제가 있습니다. 이는 접두사 압축을 무력화하고 인덱스 크기를 부풀립니다.

“점프?” - 접두사 압축은 인덱스 크기를 크게 줄여 I/O를 줄이지만, 키를 해독하려면 전체 페이지를 읽어야 합니다. 1K 페이지에서는 괜찮지만 페이지 크기가 커지면 계산 비용이 허용할 수 없게 됩니다. 따라서 각 인덱스 페이지에는 이제 압축되지 않은 항목의 오프셋을 가리키는 자체 인덱스가 있습니다. 이 인덱스를 점프 벡터라고 합니다.

Ann Harrision