MySQL 테이블을 샤딩하는 가장 좋은 방법은 무엇입니까? 내가 생각할 수있는 접근 방식은 다음과 같습니다.
- 애플리케이션 수준 분할?
- MySQL 프록시 레이어에서 샤딩?
- 샤딩을위한 중앙 조회 서버?
이 분야에서 흥미로운 프로젝트 나 도구를 알고 있습니까?
답변:
완전히 피할 수없는 경우가 아니라면 MySQL 테이블을 분할하지 않는 가장 좋은 방법입니다.
응용 프로그램을 작성할 때 일반적으로 속도와 개발자 속도를 최대화하는 방식으로 작성하려고합니다. 필요한 경우에만 지연 시간 (답변이 준비 될 때까지의 시간) 또는 처리량 (시간 단위당 응답 수)을 최적화합니다.
이러한 모든 파티션의 합계가 더 이상 단일 데이터베이스 서버 인스턴스에 맞지 않을 때만 파티션을 분할 한 다음 다른 호스트 (= 샤드)에 할당합니다. 그 이유는 쓰기 또는 읽기 때문입니다.
쓰기 사례는 a) 쓰기 빈도로 인해이 서버 디스크에 영구적으로 과부하가 걸리거나 b) 너무 많은 쓰기가 진행되어이 복제 계층에서 복제가 영구적으로 지연됩니다.
샤딩의 읽기 사례는 데이터의 크기가 너무 커서 데이터의 작업 세트가 더 이상 메모리에 맞지 않고 데이터 읽기가 대부분의 시간 동안 메모리에서 제공되는 대신 디스크에 도달하기 시작하는 경우입니다.
당신이 경우에만 이 샤딩하는 당신은 그것을 할.
샤딩하는 순간 여러 가지 방법으로 비용을 지불하게됩니다.
대부분의 SQL은 더 이상 선언적이지 않습니다.
일반적으로 SQL에서는 원하는 데이터를 데이터베이스에 알리고 해당 사양을 데이터 액세스 프로그램으로 전환하기 위해 옵티 마이저에 맡깁니다. 유연성이 있고 이러한 데이터 액세스 프로그램을 작성하는 것은 속도에 해를 끼치는 지루한 작업이기 때문입니다.
분할 된 환경에서는 노드 B의 데이터에 대해 노드 A의 테이블을 조인하거나 노드 A 및 B의 노드보다 큰 테이블이 있고 노드 B 및 C에있는 데이터에 대해 데이터를 조인 할 수 있습니다. 이를 해결하기 위해 (또는 MySQL 클러스터를 재창조하고 있음) 애플리케이션 측 해시 기반 조인 해결을 수동으로 작성하기 시작했습니다. 즉, 더 이상 선언적이지 않지만 절차 적 방식으로 SQL 기능을 표현하는 많은 SQL로 끝납니다. (예를 들어, 루프에서 SELECT 문을 사용하고 있습니다).
많은 네트워크 지연이 발생합니다.
일반적으로 SQL 쿼리는 로컬에서 확인할 수 있으며 옵티마이 저는 로컬 디스크 액세스와 관련된 비용을 알고 비용을 최소화하는 방식으로 쿼리를 해결합니다.
분할 된 환경에서 쿼리는 네트워크를 통해 여러 노드에 대한 키-값 액세스를 실행하거나 (왕복 당 개별 키 조회가 아닌 일괄 키 액세스를 사용하여) WHERE
절의 일부를 가능한 노드로 푸시 하여 해결됩니다. 적용 ( '조건 푸시 다운'이라고 함) 또는 둘 다.
그러나 최상의 경우에도 이것은 로컬 상황보다 더 많은 네트워크 왕복을 포함하며 더 복잡합니다. 특히 MySQL 옵티마이 저는 네트워크 대기 시간에 대해 전혀 알지 못하기 때문에 (예, MySQL 클러스터는 천천히 향상되고 있지만 클러스터 외부의 바닐라 MySQL의 경우 여전히 사실입니다).
SQL의 많은 표현력을 잃고 있습니다.
그다지 중요하지 않을 수 있지만 데이터 무결성을위한 외래 키 제약 조건 및 기타 SQL 메커니즘은 여러 샤드를 확장 할 수 없습니다.
MySQL에는 작동하는 비동기 쿼리를 허용하는 API가 없습니다.
동일한 유형의 데이터가 여러 노드에있는 경우 (예 : 노드 A, B 및 C의 사용자 데이터) 이러한 모든 노드에 대해 수평 쿼리를 해결해야하는 경우가 많습니다 ( "90 일 동안 로그인하지 않은 모든 사용자 계정 찾기 이상"). 데이터 액세스 시간은 여러 노드가 병렬로 요청되고 결과가 들어오는대로 집계되지 않는 한 노드 수에 따라 선형 적으로 증가합니다 ( "Map-Reduce").
이를위한 전제 조건은 비동기 통신 API이며, MySQL에는 좋은 작동 형태로 존재하지 않습니다. 대안은 시즌 패스의 세계를 방문하는 자식 프로세스의 많은 포크와 연결입니다.
샤딩을 시작하면 데이터 구조와 네트워크 토폴로지가 애플리케이션의 성능 포인트로 표시됩니다. 합리적으로 잘 수행하려면 애플리케이션이 이러한 사항을 인식해야하며 이는 실제로 애플리케이션 수준 분할 만 의미가 있음을 의미합니다.
문제는 자동 샤딩 (예 : 기본 키를 해싱하여 어떤 행이 어떤 노드로 이동하는지 결정)을 원하거나 수동 방식으로 기능적으로 분할하려는 경우 ( "xyz 사용자 스토리와 관련된 테이블은 master, abc 및 def 관련 테이블은 해당 마스터로 이동합니다. ").
기능적 분할은 사용자 스토리와 관련된 모든 테이블을 로컬에서 사용할 수 있기 때문에 제대로 수행하면 대부분의 개발자에게 보이지 않는다는 장점이 있습니다. 이를 통해 가능한 한 오랫동안 선언적 SQL의 이점을 누릴 수 있으며 네트워크 간 전송 횟수를 최소화하기 때문에 네트워크 지연 시간도 줄어들 것입니다.
기능적 샤딩은 단일 테이블이 하나의 인스턴스보다 클 수 없다는 단점이 있으며 디자이너의 수동주의가 필요합니다.
기능적 샤딩은 너무 크지 않은 많은 변경으로 기존 코드베이스에 비교적 쉽게 수행 할 수 있다는 장점이 있습니다. http://Booking.com 은 지난 몇 년 동안 여러 번 해왔으며 잘 작동했습니다.
모든 것을 말하면서 귀하의 질문을 보면 귀하가 잘못된 질문을하고 있다고 생각하거나 귀하의 문제 진술을 완전히 오해하고 있습니다.
애플리케이션 레벨 샤딩 : dbShards는 "애플리케이션 인식 샤딩"을 수행하는 유일한 제품입니다. 웹 사이트에는 몇 가지 좋은 기사가 있습니다. 정의상 애플리케이션 인식 샤딩이 더 효율적입니다. 응용 프로그램이 트랜잭션을 조회하거나 프록시에 의해 리디렉션되지 않고 트랜잭션과 함께 이동해야 할 위치를 정확히 알고 있다면 자체적으로 더 빠를 것입니다. 누군가가 샤딩을 조사 할 때 속도는 유일한 문제는 아니지만 주요 관심사 중 하나입니다.
어떤 사람들은 프록시로 "샤딩"하지만 내 눈에는 샤딩의 목적을 무너 뜨립니다. 트랜잭션에 데이터를 찾을 위치 또는 저장할 위치를 알리기 위해 다른 서버를 사용하고 있습니다. 애플리케이션 인식 샤딩을 사용하면 애플리케이션이 자체적으로 어디로 가야하는지 알 수 있습니다. 훨씬 더 효율적입니다.
이것은 실제로 # 2와 동일합니다.
이 분야에서 흥미로운 프로젝트 나 도구를 알고 있습니까?
이 공간의 몇 가지 새로운 프로젝트 :
Shard-Query 는 MySQL 용 OLAP 기반 샤딩 솔루션입니다. 분할 된 테이블과 분할되지 않은 테이블의 조합을 정의 할 수 있습니다. 분할되지 않은 테이블 (예 : 조회 테이블)은 분할 된 테이블에 자유롭게 조인 할 수 있으며, 분할 된 테이블이 분할 키로 조인되는 한 분할 된 테이블은 서로 조인 될 수 있습니다 (샤드 경계를 교차하는 교차 분할 또는 자체 조인 없음). OLAP 솔루션이기 때문에 Shard-Query는 일반적으로 간단한 쿼리의 경우에도 최소 응답 시간이 100ms 이하이므로 OLTP에서는 작동하지 않습니다. Shard-Query는 빅 데이터 세트를 병렬로 분석하도록 설계되었습니다.
MySQL 용 OLTP 샤딩 솔루션도 있습니다. 폐쇄 형 소스 솔루션에는 ScaleDB , DBShards가 포함됩니다 . 오픈 소스 OLTP 솔루션에는 JetPants , Cubrid 또는 Flock / Gizzard (Twitter 인프라)가 포함됩니다.
물론 응용 수준.
내가이 책에서 찾은 최고의 접근 방식
고성능 MySQL http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064
간단한 설명 : 데이터를 여러 부분으로 분할하고 각 서버에 최대 50 개의 부분을 저장할 수 있습니다. 두 번째로 큰 샤딩 문제인 재조정을 피하는 데 도움이됩니다. 그중 일부를 새 서버로 옮기면 모든 것이 잘됩니다. :)
나는 당신이 그것을 구입하고 "mysql 스케일링"부분을 읽을 것을 강력히 추천합니다.
2018 년에는 이에 대한 MySql 네이티브 솔루션이있는 것 같습니다. 실제로 적어도 2 개 -InnoDB 클러스터 및 NDB 클러스터가 있습니다 (상용 및 커뮤니티 버전이 있습니다).
MySql 커뮤니티 에디션을 사용하는 대부분의 사람들은 InnoDB 엔진에 더 익숙하기 때문에 이것이 최우선 순위로 탐색되어야합니다. 즉시 복제 및 파티셔닝 / 샤딩을 지원하며 다양한 라우팅 /로드 밸런싱 옵션을 위해 MySql 라우터를 기반으로합니다.
테이블 생성 구문을 변경해야합니다. 예를 들면 다음과 같습니다.
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );
(이것은 네 가지 파티션 유형 중 하나 일뿐입니다 )
매우 중요한 제한 사항 :
InnoDB 외래 키와 MySQL 파티셔닝은 호환되지 않습니다. 분할 된 InnoDB 테이블은 외래 키 참조를 가질 수 없으며 외래 키가 참조하는 열을 가질 수 없습니다. 외래 키가 있거나 외부 키에 의해 참조되는 InnoDB 테이블은 분할 할 수 없습니다.
PARTITION BY HASH(YEAR...)
스캔 모두 당신이 날짜 범위가있는 경우 파티션을. 왝.