MySQL에서 테이블 분할. 좋은 연습?


14

기존 프로젝트에서 작업을 시작했으며 이전 개발자는 동일한 스키마이지만 데이터가 다른 10 개의 개별 테이블로 테이블을 분할했습니다.

테이블은 다음과 같습니다.

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

기본 키는 정수 id필드입니다. 애플리케이션은 해시 알고리즘 ( idmod 10)을 사용하여 조회를 수행 할 때 액세스 할 테이블을 알고 있습니다. 예를 들어 id= 10은 결과 [tableName_0]입니다.

결합하면 테이블의 행 수가 10 만 개이고 성장률이 상대적으로 낮습니다.

따라서 내 질문은 이것이 가능한 솔루션인지 여부 또는 어떤 상황에서도 좋은 습관인지 여부입니다. 내 이론은 UNIONs 등을 쉽게 할 수 있도록 조합하여 사용하는 것 입니다. 주요 단점은 모든 응용 프로그램 코드와 장기적으로 가치가 있는지 여부를 변경하는 것입니다.

답변:


17

나는 모든 사람들이 이것을 너무 복잡하게 생각합니다. 여기서 핵심은 다음과 같습니다.

결합하면 테이블의 행 수가 10 만 개이고 성장률이 상대적으로 낮습니다.

이것은 RDBMS가 처리 할 수있는 케이크 입니다. 하나의 테이블로 이동하여 올바르게 색인화하고 해결 된 문제로 간주하십시오.

수십억 행 이상을 고려하여 매우 많은 양의 데이터를 처리하기 시작할 때까지 "집에서"또는 다른 방식으로 분할을 고려할 필요가 없습니다.


3

병합 테이블을 사용할 수 있지만 4.x 버전에서 더 구식입니다. 응용 프로그램이 a) 실제로 이전 버전을 실행 중이거나 b) 원래 개발자가 테이블 파티션을 인식하지 못했기 때문에 수동으로 분할되어 있다고 가정하면.

간단히 말해 5.1 이상을 실행하는 경우 mysql 이이 파티션을 수행하도록 할 수 있습니다. http://dev.mysql.com/doc/refman/5.1/en/partitioning.html을 참조 하십시오. 5.5를 사용하는 경우 차이점을 찾을 수 있으므로 해당 문서를 확인해야합니다.

파티셔닝에는 많은 장점이 있습니다. 그러나 실제로 데이터 세트, 액세스 패턴 및 인덱싱 방법에 따라 다릅니다. 또한, 다음 주석은 이전 mysql Merge 테이블이 아니라 mysql 5+ 파티셔닝과 관련이 있습니다. 그것들은 때때로 파티션 측면에서 논의됩니다.

몇 가지 예 :

  • 자주 액세스하는 조회 키를 기반으로하는 직선 버킷 팅 (또는 해싱) 거의 항상 기본 또는 다른 고유 키를 찾는 경우 mysql은 얼마나 많은 파티션이 있는지에 따라 검색 공간을 줄일 수 있습니다. 그러나 하나의 키로 파티션을 나눈 다음 다른 키로 자주 검색하는 경우 이는 해가 될 수 있습니다. 키로 데이터를 검색하면 데이터가 분할되지 않고 조회를 더 많이 검색해야합니다 (각 파티션마다 하나씩, b / c, 솔직히 데이터의 위치를 ​​모릅니다)
  • 날짜별로 증가하는 일시적인 레코드 세트가 있고 이전 달을 주기적으로 제거하는 상황을 고려하십시오. 날짜별로 파티션을 나누는 경우 아무리 커도 테이블을 삭제하는 것만 큼 빠른 파티션을 간단히 삭제할 수 있습니다. 이러한 테이블을 날짜별로 정리하려면 각 개별 행이 삭제되는 하나 이상의 DELETE 쿼리를 실행해야합니다. 이 단점은 mysql이이 시나리오에서 설명한 최대 날짜에 도달하면 새 파티션을 자동으로 생성하지 않는다는 것입니다. 파티션을 필요할 때 추가하려면 추가 유지 관리 스크립트가 필요합니다.
  • myisam 검사를 사용하면 복구 속도가 훨씬 빠릅니다. 100G myisam 테이블을 고려하십시오. 손상된 테이블을 복구하려면 최소한 약 100G의 여유 디스크 공간이 필요합니다. 동일한 크기의 10 개의 다른 청크로 분할 된 경우 10G의 공간 만 필요하며 빠른 복구를 위해 더 적은 key_sort_buffer 메모리가 필요합니다. 그러나 각 파티션마다 반복을 수행해야합니다.

요약하면, 파티셔닝 테이블의 일반적인 접근 방식은 많은 이점을 제공 할 수 있습니다. 그러나 액세스 패턴과 방법을 고려하지 않고 맹목적으로 적용되는 것은 마법의 총알이 아닙니다. 정확하게 분할된다.

원하는 파티셔닝이 응용 프로그램에 따라 다르고 해당 논리를 응용 프로그램 계층에 두는 것이 더 적합한 상황을 상상할 수 있습니다. 그러나 당신의 직선 계수 10 설명이 주어지면 이것은 그런 경우처럼 보이지 않습니다.

편집하다

내 설명을 작성하면서 테이블이 100K 행이라고 말한 것을 잊었습니다. 테이블의 전체 스키마와 평균 행 길이를 사용하면 확실히 말하기 어렵지만 일반적으로 하드웨어 크기가 중간 정도 인 경우에도 중간 크기로 들립니다. 동시에, 그것이 현재 또는 예측 가능한 미래의 방식으로 문제를 일으키지 않는다면, 시간을 소비하지 말고 그것을 바꾸어 위험을 초래하십시오.


3

이전 개발자가 수행 한 작업은 자체 파티션 별 구현을 빌드 한 것입니다. MySQL은 문자 그대로 MySQL 5.1에서 이것을 기본적으로 지원합니다.

http://dev.mysql.com/doc/refman/5.1/en/partitioning-hash.html

나는 정당한 이유를 생각할 수 없으므로 기본 버전에 의존하기보다는 해시별로 파티션을 구현해야합니다 [1]. 스키마 변경을 수행하는 것은 악몽입니다.

또한 파티션 별 해시 (기본 구현)를 거의 권장하지 않습니다. 나는 그것을 사용하여 한 번에 각 파티션을 병렬로 검색 할 수 있다면 유용 할 것이라고 생각합니다 (MySQL은 그렇지 않습니다). 여러 파티션을 검색해야하는 경우 설명한 구성표가 훨씬 느려질 수 있습니다.

[1] 그러나 일부 다른 파티션 유형의 경우 고유 한 파티션을 롤링하는 것이 좋습니다. MySQL은 파티션 키를 기본 키와 모든 고유 인덱스의 일부로 만들도록합니다.


2

질문에 대한 답변 :

이것이 가능한 솔루션인지 아닌지

IMHO, 이것은 불필요한 오버 헤드처럼 보입니다. 설명에 공개되지 않은 다른 정보가없는 한 단일 테이블을 올바르게 인덱싱하고 파티션을 나눌 수 있습니다.

질문에 대한 답변 :

... 어떤 상황에서도 좋은 습관이라면

IMHO, 수직 샤딩은 상황에 따라 의미가 있습니다. 이것을 보면 일반적으로 일종의 로그 형식입니다. 우리가 웹 서버 로그에 이것을 사용한다고 가정하고 월별로 파티션을 나누고 싶습니다. 매일 기존 테이블을 변경하는 대신 매일 새 테이블을 작성하고 해당 테이블에 행을 로그 할 수 있습니다.

예를 들어 웹 로그 테이블은 다음과 같은 형식을 취할 수 있습니다.

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

솔루션은 웹 로그 데이터베이스에서 필요에 따라 테이블을 작성합니다.

weblogs.20120301
weblogs.20120302
weblogs.20120303

기타

이러한 방식으로 데이터를 유지 관리하고 검색 할 수 있습니다. 추출은 정상적인주기 과정이됩니다. 오래된 데이터에 대한 작업으로 인해 연속 작업이 잠기지 않습니다.

제시 한 시나리오에서 어쨌든 구조에 고정되어 있으므로이 목적에 최적화 된 단일 테이블을 사용하지 않는 이유는 무엇입니까? 알고리즘 기반의 행 저장은 스케치가되고 오류가 발생하기 쉽습니다.


0

쿼리가 막대한 데이터를 대상으로하는 경우 쿼리 조건에 따라 데이터를 분할하면 성능이 크게 향상됩니다. 그러나 이러한 분할은 몇 가지 프로그래밍 문제를 일으 킵니다.

문제는 : 분할이 성능에 가치가 있습니까, 아니면 성능에 해를 끼치나요?

여러 테이블에서 여러 행을 잠글 필요가있는 트랜잭션이 있고 여기에 문제점 (예 : 교착 상태 또는 트랜잭션 제한 시간 초과)이있는 경우이를 단일 테이블로 결합하고 SQL을 다시 작성하여 문제를 복구 할 수 있습니다.

테이블을 분할할지 여부를 생각할 때 성능 향상과 프로그래밍 복잡성 간의 균형을 고려했습니다.

상황에 따라 기존 코드를 수정하면 코드를보다 쉽게 ​​유지 관리 할 수있는 장기적인 솔루션이 될 수 있습니다. 메타 프로그래밍 시도를 제안합니다. 예를 들어, StringTemplate 을 사용하여 SQL을 동적으로 생성하십시오. 기존 코드의 수정이 너무 어려운 경우 메타 프로그래밍 엔진에서 SQL을 생성하고 싶습니다.


0

파일을 테이블에 저장해야 할 때이 방법론을 사용하면 내보내기, 복구 및 복원에 도움이됩니다.

10GB로 분할 된> 30Gb의 테이블이 있습니다. 이 테이블에는 ID-BLOB 만 있으며 나에게 쉽게 보관할 수 있습니다. 그리고 INISADB 버퍼를 저장하기 위해 MyISAM을 사용합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.