programing

Oracle의 NULL 스토리지

batch 2023. 7. 20. 21:47
반응형

Oracle의 NULL 스토리지

Oracle 11g Standard One Edition에 대한 표가 있습니다.

표 1.

col1 col2 col3 col4 col5 col6 col7 col8       col9 col10 col11
1    NULL 2    3    4    5    NULL NULL       19   21    22
1    NULL 2    3    4    5    NULL 1 Jan 2009 19   21    22
1    NULL 2    3    4    5    NULL NULL       19   21    22
1    9    2    3    4    5    A    NULL       19   21    22
1    NULL 2    3    4    5    B    NULL       19   21    22

표 설명은 다음과 같습니다.

Name                 Null Type          
-------------------- ---- ------------- 
COL1                      NUMBER        
COL2                      NUMBER        
COL3                      NUMBER        
COL4                      NUMBER       
COL5                      NUMBER        
COL6                      NUMBER        
COL7                      VARCHAR2(255) 
COL8                      DATE          
COL9                      DATE  
COL10                     DATE        
COL11                     VARCHAR2(255) 

NULL 값을 사용하여 테이블이 사용하는 스토리지의 백분율을 확인해야 합니다.

예: 사용되는 테이블 1 스토리지는 1GB이고 테이블 1 내부의 NULL은 100MB를 사용하므로 NULL은 스토리지의 10%를 차지합니다.

또한 오라클에 NULL의 대체 표현이 있습니까?

테이블의 NULL은 스토리지 공간의 1.75%만 사용할 수 있습니다.

하지만 그 숫자는 아래 재현 가능한 테스트 사례를 기준으로 하더라도 의미가 없습니다.NULL은 매우 작다는 것을 이해하는 것이 더 중요합니다(단 1바이트).너무 작아서 "실제" 크기는 극단적인 경우를 제외하고는 무관해야 합니다.너무 작아서 대체 표현에 대해 걱정하는 것은 거의 항상 시간 낭비입니다.


모범 사례 테스트 사례(실용 공간 사용)

테이블 정의를 사용하여 1GB의 데이터를 생성합니다.먼저 테이블을 생성합니다.

create table test1(
COL1  NUMBER,
COL2  NUMBER,
COL3  NUMBER,
COL4  NUMBER,
COL5  NUMBER,
COL6  NUMBER,
COL7  VARCHAR2(255),
COL8  DATE,
COL9  DATE,
COL10 DATE,
COL11 VARCHAR2(255)
) pctfree 0 /* Let's assume no updates or deletes, and pack the data tightly */;

이제 1기가바이트의 데이터를 생성합니다.각 값은 해당 데이터 유형에 대해 가능한 가장 큰 값을 사용합니다.

begin
    for i in 1 .. 15 loop  --Magic number to generate exactly 1GB.
        insert into test1
        select
            .0123456789012345678901234567890123456789,
            .0123456789012345678901234567890123456789,
            .0123456789012345678901234567890123456789,
            .0123456789012345678901234567890123456789,
            .0123456789012345678901234567890123456789,
            .0123456789012345678901234567890123456789,
            lpad('A', 255, 'A'),
            sysdate,
            sysdate,
            sysdate,
            lpad('A', 255, 'A')
        from dual
        connect by level <= 95000;    --Magic number to generate exactly 1GB.
        commit;
    end loop;
end;
/

이러한 쿼리는 1,425,000 행에 1GB의 공간을 사용한다는 것을 보여줍니다.

select count(*) from test1;
select bytes/1024/1024/1024 gb from user_segments where segment_name = 'TEST1';

행 행 수는 두 표를 .NULL란에.

create table test1_null as
select col1+null c1, col2+null c2, col3+null c3, col4+null c4, col5+null c5, col6+null c6,
    cast(null as varchar2(255)) c7, col8+null c8, col9+null c9, col10+null c10,
    cast(null as varchar2(255)) c11
from test1;

새 세그먼트 크기는 0.0175GB 또는 1.75%에 불과합니다.

select bytes/1024/1024/1024 gb from user_segments where segment_name = 'TEST1_NULL';

그 테스트 사례가 오해의 소지가 있는 이유

이것이 간단한 질문처럼 들릴 수 있지만, 그것에 완전히 대답하기 위해서는 전체 책이나 수정 구슬이 필요합니다.실제 스토리지 크기를 얻는 것은 터무니없이 복잡합니다.적어도 다음과 같은 문제에 대해 생각해 볼 필요가 있습니다.

  1. 가변 너비 데이터.대부분의 Oracle 데이터 유형은 데이터를 저장하는 데 필요한 공간만 사용합니다.따라서 NULL 바이트에 사용되는 스토리지의 백분율은 다른 열의 내용에 따라 달라집니다.CHAR, NCAR, DATE, TIMESTAMP 등 데이터에 관계없이 정적인 양의 스토리지를 사용하는 데이터 유형은 거의 없습니다.
  2. 뒤에 오는 null.행 끝에 있는 모든 연속된 NULL은 한 바이트에 저장됩니다.기본 압축이 활성화되지 않은 경우 모든 NULL이 다시 바이트를 사용합니다.
  3. 머리 위에 노를 젓습니다.모든 행에는 열 및 구성에 따라 오버헤드가 있습니다.테이블이 얇을수록 행 오버헤드가 공간을 더 많이 사용하므로 NULL에서 사용되는 백분율이 변동합니다.
  4. 오버헤드 차단.이는 행 수에 따라 달라집니다. 다음과 같은 설정PCTFREE이전 행이 삭제된 경우, 테이블이 마지막으로 재구성된 시간, 블록 크기 등.
  5. 세그먼트 오버헤드.공간이 익스텐트 청크로 할당됩니다.익스텐트 관리는 기본 알고리즘(최대 64MB까지 1MB 청크로 할당)을 사용하거나 임의의 사용자 지정 값일 수 있습니다.이 오버헤드는 데이터 양에 따라 관련성이 낮아집니다.테이블 공간이 10GB와 같이 매우 균일한 익스텐트 크기로 설정되어 열 값에 관계없이 많은 공간이 낭비될 수 있습니다.
  6. 기타 I/O 오버헤드.ASM, 운영 체제, SAN 등으로 인해 공간이 낭비될 수도 있습니다.

행 조각의 형식(이론상 공간 사용)

아래 이미지는 개념 가이드의 논리적 스토리지 구조 장에서 가져온 것입니다.

enter image description here

열 데이터는 일련의 열 길이 및 열 값으로 구성됩니다.값이 NULL이면 열 길이가 0으로 설정되고 열 값에 공백이 사용되지 않습니다.따라서 NULL은 항상 숫자 0에 대해 1바이트만 사용합니다.

NULL이입니다. 데이터 은 1바이트 이상입니다. 정적 데이터 유형은 다음과 같습니다.DATE에서는 길이에 대해 1바이트를 사용한 다음 값에 대해 7바이트를 사용합니다.다시 말하지만, 날짜가 NULL이 아닌 경우 길이는 0으로 설정되고 값은 비어 있습니다.

이 이미지는 "추적 NULL" 저장 트릭에 대해서도 설명할 수 있습니다.뒤에 Null이 있을 경우 Oracle은 열 수를 더 낮게 설정하고 마지막 열 길이를 0으로 유지하며 나머지 열도 NULL임을 유추합니다.

대체 표현?

이제 의심이 갑니다.NULL의 대체 표현에 대해 질문하면 다음과 같은 네 가지 유형의 사람들이 떠오릅니다.

  1. 관계형 모델을 위반하는 것에 대해 불평하고 수십 년 동안 잘 작동해온 도구 대신 모호한 도구를 사용할 것을 제안하는 절망적으로 이론적인 사람들.
  2. 방대한 엔티티-속성-값 표가 항상 정답이라고 생각하는 데이터 설계자."이봐요, 제 PDF에 좋아 보이는데, 질문이 불가능해도 누가 신경 쓰겠어요?"
  3. SQL에 익숙하지 않고 NULL이 작동하는 방식에 실망한 사람들.
  4. 질문에 너무 많은 내용을 읽는 오버플로 사용자를 스택합니다.(따라서 제가 멀리 떨어져 있다면 언제든지 이 질문의 배경에 대한 정보를 추가하세요!)

네, NULL은 좀 이상합니다.하지만 곧 이해가 될 것입니다.공간이나 NULL을 완전히 피하는 방법에 대해 너무 걱정하지 마십시오.NULL에 대해 지불하는 가격은 NULL을 완전히 피하는 안티패턴에 대해 지불하는 가격과 비교하면 아무것도 아닙니다.

먼저 테이블 속성(파티션, 인덱스, 데이터 유형, 로브 필드 등), 파일 시스템 및 기타 요인에 따라 달라집니다.이전에도 오라클 11에 대해 비슷한 작업을 수행했습니다.다음은 제가 수행한 단계입니다(데이터베이스에는 3000개 이상의 테이블이 있기 때문에 크기 때문에 매우 정확할 필요가 없었습니다).

나의 알고리즘

  1. null 없이 테이블의 복사본을 만듭니다(1000개의 레코드).
  2. null로만 복사본 만들기(1000개의 레코드);
  3. 를 사용하여 열당 null을 카운트합니다(이 값은 null의 양이 더 많은 열을 확인하기 위해 자동화할 수 있음).

    열이 null인 테이블에서 카운트(*)를 선택합니다.

  4. 마지막 측정값(1,000개의 레코드)만을 기준으로 사본을 작성합니다.

결과를 분석합니다.

그가 당신에게 도움이 되기를 바랍니다.

참고: 적어도 저의 경우에는 데이터베이스 사용량을 분석하고 정리하는 것이 목표였습니다.

이 주제에 대한 자세한 내용은 다음과 같습니다.

NULL 값이 스토리지 공간을 늘립니까?

표에서 행 크기를 계산하는 방법은 무엇입니까?

언급URL : https://stackoverflow.com/questions/37144363/null-storage-in-oracle

반응형