2010-05-26 1 views
7

다른 스토리지 엔진에 필요한 스토리지 요구 사항을 파악하려고합니다. 나는 어떤 값을 삽입 한 후 나는 다음과 같은 얻을 show table status;을 실행하면InnoDB 테이블 크기가 예상보다 훨씬 큰 이유는 무엇입니까?

CREATE TABLE `mytest` (
    `num1` int(10) unsigned NOT NULL, 
    KEY `key1` (`num1`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

: :이 테이블이

 
+----------------+--------+---------+------------+---------+----------------+-------------+------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-------------------+----------+----------------+---------+ 
| Name   | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time   | Update_time   | Check_time | Collation   | Checksum | Create_options | Comment | 
+----------------+--------+---------+------------+---------+----------------+-------------+------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-------------------+----------+----------------+---------+ 
| mytest   | InnoDB |  10 | Compact | 1932473 |    35 | 67715072 |    0 |  48840704 | 4194304 |   NULL | 2010-05-26 11:30:40 | NULL    | NULL  | latin1_swedish_ci |  NULL |    |   | 

공지 사항 AVG_ROW_LENGTH 내가 InnoDB하지만 공간을보다 효율적으로 사용할 수 있도록하지 않을 것이라고 당황하고 35입니다 내가 null이 아닌 정수를 저장할 때.

동일한 테스트를 myISAM에서 실행했으며 기본적으로 myISAM은이 테이블에서 행당 7 바이트를 사용합니다. 내가 실행할 때

ALTER TABLE mytest MAX_ROWS=50000000, AVG_ROW_LENGTH = 4; 

결국 myISAM은 마침내 5 바이트 행을 올바르게 사용하게됩니다.

InnoDB에 대해 동일한 ALTER TABLE 문을 실행하면 avg_row_length가 변경되지 않습니다.

왜 4GB의 부호없는 정수만 저장할 때 왜 큰 avg_row_length가 필요합니까?

+0

InnoDB는 데이터와 인덱스 모두에 테이블 스페이스를 사용합니다. 이것은 의미가 있으며, 왜 이렇게 큰 avg_row_length ...를 보는지 이유가 될 것 같습니다. 또한 각 리프 노드는 트랜잭션 ID와 롤백 포인터를 저장한다는 것을 알게되었습니다. 그럼 나는 당 거래를 사용하지 않으므로이 데이터를 사용하지 않아도된다. 이 값을 저장하지 않는 방법이 있습니까? 어떤 식 으로든 InnoDB를 사용할 수 있지만 스토리지를 좀 더 잘 활용할 수 있습니까? 덕분에 ! –

+0

@alessandro : 예, 트랜잭션 지원은 약간의 오버 헤드도 추가합니다. 트랜잭션을 사용하지 않는다고해서 사용되지 않는다는 의미는 아닙니다. 예를 들어 긴 UPDATE 작업 중에 죽은 스레드는'InnoDB'에서 올바르게 롤백되지만 MyISAM에서는 롤백되지 않습니다. 트랜잭션 지원은'InnoDB' 사용의 요점입니다. 필요하지 않다면'MyISAM' 만 사용하십시오. – Quassnoi

+0

@Quassnoi : MyISAM이 InnoDB로서의 "성숙한"또는 생산 준비가되지 않았다는 인상을 받았습니다. 아마 그것은 근거없는 공포입니다. MyISAM이 일관성을 보장하기 위해 전체 테이블 잠금을 필요로한다는 사실 외에도 데이터베이스를 백업 할 때 MyISAM이 테이블에 가져 오는 어려움이 있습니까? 나는 거래를 요구하지 않으며 나는 많은 양의 데이터를 저장할 것이다. MyISAM에 알려진 문제가있어 사용하지 않을 것입니까? –

답변

10

InnoDB 테이블이 클러스터되어 있으면 PRIMARY KEY을 키로하고 모든 다른 열을 페이로드로 사용하여 모든 데이터가 B-Tree에 포함된다는 것을 의미합니다.

명시 적으로 PRIMARY KEY을 정의하지 않으므로 InnoDB은 숨겨진 6 바이트 열을 사용하여 레코드를 정렬합니다.

B-Tree 조직의 오버 헤드 및 리프 리프 블록이 아닌 리프 블록의 오버 헤드에는 sizeof(int) * num_rows보다 많은 공간이 필요합니다.

0

Quassnoi의 매우 훌륭한 답변 외에도 중요한 데이터 세트를 사용해보십시오.

내가 할 수있는 것은 1M 행의 시뮬레이션 된 생산 데이터를로드 한 다음 테이블 크기를 측정하고이를 가이드로 사용하는 것입니다. 여기에 무엇을 I've done in the past anyway

+0

예, 감사합니다. MarkR, 저는 50M 행의 데이터 세트로이 작업을 수행했습니다. InnoDB는 3GIG에서 3 배 이상의 공간을 사용했습니다. –

+0

내 연구 (위의 링크 참조)에 따르면 이는 일반적인 현상입니다. 플러그인을 사용하고 압축을 켜서 공간을 적게 차지할 수 있습니다. 일부 데이터는 내 블로그 게시물을 참조하십시오. – MarkR

2

있어

당신이 유용 수있는 몇 가지 추가 정보를 원하시면입니다.

InnoDB는 16KB 페이지 단위로 데이터를 할당하므로 몇 개의 행만 있고 테이블이 < 16K 인 경우 'SHOW TABLE STATUS'로 인해 행 크기가 늘어납니다. 예를 들어, 4 행의 평균 행 크기는 4096으로 되돌아갑니다.

"보이지 않는"기본 키에 대한 행당 추가 6 바이트는 공간을 고려해야 할 중요한 포인트입니다. 테이블은 하나의 열이있는 경우, 즉 기본 키를 만들 수있는 이상적인 열이있는 값을 가정의가 고유 :

CREATE TABLE `mytest2` 
     (`num1` int(10) unsigned NOT NULL primary key) 
ENGINE=InnoDB DEFAULT CHARSET=latin1; 

이 같은 PRIMARY KEY를 사용하여 :

  1. 없음 INDEX 또는 보조 색인이 없기 때문에 KEY 절이 필요합니다. InnoDB 테이블의 인덱스 구성 형식은 무료 키의 기본 키 값을 기반으로 빠른 검색을 제공합니다.
  2. NUM1 열 데이터의 다른 사본으로 그 열을 명시 적으로 색인화 할 때 발생하는 일은 발생하지 않습니다.
  3. 6 바이트의 보이지 않는 기본 키 값의 다른 복사본을 만들지 마십시오. 기본 키 값은 각 2 차 인덱스에 복제됩니다. 10 열이있는 테이블에 10 개의 인덱스를 사용하지 않으려는 경우가 많으며 여러 개의 다른 열을 결합하거나 긴 문자열 열인 기본 키가 필요하지 않을 수도 있습니다.

전반적으로 기본 키만 쓰면 테이블 + 인덱스와 관련된 데이터가 줄어 듭니다. 전체 데이터 크기의 감각을 얻으려면, 나는

set innodb_file_per_table = 1; 

으로 실행하고 데이터의 크기/데이터베이스 /*table*.ibd 파일을 검사하고 싶다. 각각의 .ibd 파일에는 InnoDB 테이블에 대한 데이터와 모든 관련 색인이 들어 있습니다.

빨리 나는 보통과 같이 성명을 실행, 테스트를 위해 큰 테이블을 빌드하려면 데이터의 양마다 두 배로

insert into mytest 
select * from mytest; 

합니다. 값이 고유하게 가지고 있기 때문에 기본 키를 사용하여 단일 열 테이블의 경우, 나는이 서로 충돌에서 값을 유지하기 위해 변화를 사용 :

insert into mytest2 
select num1 + (select count(*) from mytest2) from mytest2; 

이 방법을, 나는 할 수 있었다 공간의 오버 헤드는 포인터 스타일 메커니즘을 사용하여 개별 행을 빠르게 검색하기를 원한다는 가정에 기반하고 대부분의 테이블은 값이 포인터 (예 : 기본 키)를 사용하여 합계, 평균 및 표시되는 실제 데이터가있는 열을 확인할 수 있습니다.

+0

멋진 정보를 공유해 주셔서 감사합니다. – dkamins