TiDB 소스 코드 읽 기 시리즈 글 (10) Chunk 와 실행 프레임 워 크 소개

6102 단어
Chunk 가 뭐야?
TiDB 2.0 에서 저 희 는 Chunk 라 는 데이터 구 조 를 도입 하여 메모리 에 내부 데 이 터 를 저장 하고 메모리 의 배분 비용 을 줄 이 며 메모리 의 점용 을 낮 추고 메모리 사용량 통계 / 통 제 를 실현 합 니 다. 그 특징 은 다음 과 같 습 니 다.
  • 읽 기 전용
  • 무 작위 쓰기 지원 하지 않 음
  • 추가 작성 만 지원
  • 열 저장, 같은 열의 데 이 터 를 연속 으로 메모리 에 저장
  • Chunk 는 본질 적 으로... Column 의 집합 은 메모리 에 같은 열의 데 이 터 를 연속 으로 저장 하 는 것 을 책임 집 니 다. 다음은 Column 의 실현 을 살 펴 보 겠 습 니 다.
    1. Column
    Column 의 구현 은 Apache Arrow, Column 의 코드 를 참고 합 니 다. 여기 요.저 장 된 데이터 형식 에 따라 저 희 는 두 가지 Column 이 있 습 니 다.
  • 정장 Column: 정장 유형의 데 이 터 를 저장 합 니 다. 예 를 들 어 Double, Bigint, Decimal
  • 길 어 지 는 Column: 길 어 지 는 유형의 데 이 터 를 저장 합 니 다. 예 를 들 어 Char, Varchar
  • 어떤 데이터 형식 은 일정한 Column 을 사용 하고, 어떤 데이터 형식 은 길 어 지 는 Column 으로 함 수 를 볼 수 있 습 니까? addColumnByFieldType 。
    Column 안에 필드 가 매우 많 습 니 다. 여기 서 간단하게 소개 하 겠 습 니 다.
  • length 는 이 Column 에 몇 줄 의 데이터 가 있 는 지 나타 낸다.
  • nullCount 는 이 Column 에 데이터 가 얼마나 있 는 지 나타 내 는 데 사 용 됩 니 다.
  • nullBitmap 는 이 Column 의 모든 요 소 를 저장 하 는 데 사 용 됩 니 다.  NULL 특별한 주의 가 필요 한 것 은 우리 가 0 표 시 를 사용 하 는 것 이다.  NULL, 1 은 비  NULL, Apache Arrow 와 같 습 니 다.
  • data 는 구체 적 인 데 이 터 를 저장 합 니 다. 길이 가 정 해 지 든 길 어 지 든 Column 이 든 모든 데 이 터 는 이 byte slice 에 저 장 됩 니 다.
  • offsets 는 길 어 진 Column 에 사용 되 며, 데이터 마다 데이터 라 는 slice 의 오프셋 을 저장 합 니 다.
  • elemBuf 가 주어진 긴 Column 을 사용 합 니 다. 데 이 터 를 읽 거나 쓸 때 encode 와 decode 를 보조 합 니 다.

  • 1.1  길이 가 아 닌 NULL 값 을 추가 합 니 다.
    하나의 요 소 를 추가 하려 면 구체 적 인 데이터 형식 에 따라 구체 적 인 append 방법 을 호출 해 야 합 니 다. 예 를 들 어 appendInt 64, appendString 등 입 니 다. 기다리다
    길이 가 정 해진 Column 은 다음 그림 과 같이 표시 할 수 있 습 니 다.
    우리 appendInt64 예 를 들 어 정 해진 형식의 데 이 터 를 추가 하 는 방법 을 살 펴 보 자.
  • 사용  NULL  append 할 데 이 터 를 먼저 복사 합 니 다. elemBuf 가운데
  • 장군 elemBuf 데이터 append data 가운데
  • 가다 nullBitmap 중 append 하나 1.

  • 위 에서 첫 번 째 단 계 는...  unsafe.Pointer  이 함수 에서 완성, 두 번 째, 세 번 째 단 계 는... finishAppendFixed 이 함수 에서 완성 되 었 습 니 다.다른 고정 유형 요소 의 추가 조작 은 매우 비슷 하 다. 관심 이 있 는 학생 들 은 이어서 appendFloat 32, appendTime 을 볼 수 있다. 등 함수.
    1.2  길 어 지 는 비 NULL 값 추가
    길 어 지 는 Column 은 다음 그림 으로 표시 할 수 있 습 니 다.
    우리 appendString 을 예 로 들 어 길 어 지 는 형식의 데 이 터 를 추가 하 는 방법 을 보 겠 습 니 다.
  • 데 이 터 를 append 에서 data 가운데
  • 가다 nullBitmap 중 append 1 개;
  • 가다 offsets 현재 data 의 size 는 다음 요소 로 data 의 시작 점 입 니 다.

  • 위 에서 첫 번 째 단 계 는... appendString 이 함수 에서 완성, 두 번 째, 세 번 째 단 계 는... finishAppendVar 이 함수 에서 완성 되 었 습 니 다.다른 변 장 유형 요소 의 추가 조작 도 매우 비슷 하 다. 관심 이 있 는 학생 들 은 이어서 appendBytes, appendJSON 을 볼 수 있다. 등 함수.
    1.3  NULL 값 추가
    우리 appendNull 함수 가 Column 에 하 나 를 추가 합 니 다.  appendInt64  값:
  • 가다 nullBitmap 중 append 1 개 0;
  • 정기 Column 이 라면 data 에 append 하 나 를 추가 해 야 합 니 다. elemBuf 길이 의 데 이 터 는 자 리 를 차지 하 는 데 쓰 인 다.
  • Column 이 길 어 지면 data 에 append 데 이 터 를 넣 지 않 고 offsets 현재 data 의 size 는 다음 요소 로 data 의 시작 점 입 니 다.

  • 2. Row
    위의 그림 에서 보 듯 이 Chunk 의 Row 는 논리 적 인 개념 이다. Row 의 데 이 터 는 Chunk 의 각 Column 에 저장 되 고 같은 Row 의 데 이 터 는 메모리 에 연속 으로 저장 되 지 않 으 며 우 리 는 Row 대상 을 가 져 올 때 데이터 복사 가 필요 하지 않다.Row 의 개념 을 제공 하 는 것 은 산 자가 운행 하 는 과정 에서 대부분 Row 단위 로 데 이 터 를 방문 하고 조작 하기 때문이다. 예 를 들 어 집합, 정렬 등 이다.
    Row 는 GetInt 64, GetString, GetMyDecimal 등 Chunk 의 데 이 터 를 얻 는 방법 을 제공 합 니 다. 등, 앞에서 Column 에 append 데 이 터 를 가 져 오 는 방법 을 소 개 했 습 니 다. 데 이 터 를 가 져 오 는 방법 은 append 데 이 터 를 반추 할 수 있 고 코드 도 간단 합 니 다. 여기 서 더 이상 상세 하 게 소개 하지 않 겠 습 니 다.
    3. 쓰다
    현재 Chunk 라 는 가방 은 대외 적 으로 Chunk, Row 등 인터페이스 만 노출 되 고 Column 이 노출 되 지 않 았 기 때문에 데 이 터 를 쓰 는 것 은 Chunk 에서 실 현 된 Column 의 구체 적 인 함수 에 대한 warpper 입 니 다. 예 를 들 어 AppendInt64;데 이 터 를 읽 는 것 은 Row 에서 실 현 된 Getxxx 함수 입 니 다. 예 를 들 어 GetInt64。
    실행 프레임 워 크 소개
    1. 오래된 실행 프레임 워 크 안내
    재 구성 하기 전에 TiDB 1.0 에서 사용 하 는 실행 프레임 워 크 는 Child 의 Next 함 수 를 계속 호출 하여 Datum 으로 구 성 된 Row (방금 소개 한 Chunk Row 와 두 개의 데이터 구조) 를 가 져 옵 니 다. 이러한 실행 방식 은 함수 가 호출 될 때마다 한 줄 의 데이터 만 되 돌려 주 고 어떤 유형의 데 이 터 를 Datum 이라는 구조 체 로 포장 하 는 것 이 특징 입 니 다.
    이런 방법의 장점 은 간단 하고 사용 하기 쉽다 는 것 이다.단점 은:
  • 처리 한 데이터 양 이 많 으 면 프레임 의 함수 호출 비용 이 매우 클 것 이다.
  • Datum 이 사용 하 는 잘못된 메모리 가 너무 크 고 메모리 낭비 가 많 습 니 다 (8 바이트 의 정 수 를 저장 하려 면 56 바이트 가 필요 합 니 다).
  • Datum 은 중용 되 지 않 았 고 golang 의 gc 압력 이 크다.
  • Operator 마다 한 줄 의 데이터 만 출력 하고 캐 시 우호 적 인 계산 을 하 며 CPU 를 충분히 이용 하 는 pipeline 은 매우 어렵다.
  • Datum 의 interface 형식의 데 이 터 는 메모리 사용량 을 통계 하 는 데 어려움 을 겪 습 니 다.

  • 2. 새 실행 프레임 워 크 소개
    재 구성 후 TiDB 2.0 에서 사용 하 는 실행 프레임 워 크 는 Child 를 계속 호출 합 니 다. NextChunk 함수, Chunk 데 이 터 를 가 져 옵 니 다.
    이런 집행 방식 의 특징 은:
  • 매번 함수 호출 시 데 이 터 를 되 돌려 줍 니 다. 데 이 터 는 하나의 이름 NULL 입 니 다. 기본 값 은 1024 줄 입 니 다.TiDB 는 TP 와 AP 를 혼합 한 데이터베이스 이기 때문에 AP 유형의 조회 에 있어 서 는 계 산 된 데 이 터 량 이 많 기 때문에 1024 는 문제 가 없 지만 TP 요청 에 있어 서 는 계 산 된 데 이 터 량 이 비교적 적 을 수 있 으 며, 1024 줄 의 메모 리 를 처음부터 분배 하 는 것 이 최선 의 실천 은 아니다.(여기 github issue 가 이 문 제 를 토론 하고 있 습 니 다. 관심 있 는 친구 들 이 토론 하고 해결 하 는 것 을 환영 합 니 다)
  • Child 는 이 데 이 터 를 Parent 에서 내 려 온 Chunk 에 기록 합 니 다.
  • 이런 집행 방식 의 장점 은:
  • 프레임 워 크 의 함수 호출 비용 을 줄 였 습 니 다. 예 를 들 어 1024 줄 을 같은 출력 한 결과 현재 함수 호출 횟수 는 이전 1 / 1024 가 될 것 입 니 다.
  • 메모리 사용 이 더욱 효율 적 입 니 다. Chunk 의 데이터 조직 은 매우 치밀 합 니 다. 8 바이트 의 정 수 는 거의 8 바이트 만 필요 하고 다른 추가 메모리 비용 은 없습니다.
  • golang 의 gc 압력 을 줄 였 습 니 다. Chunk 가 사용 하 는 메모 리 는 끊임없이 재 활용 할 수 있 습 니 다. 새 메모 리 를 자주 신청 하지 않 아 도 됩 니 다.
  • 검색 의 실행 과정 은 더욱 캐 시 친화 적 입 니 다. 앞서 말 했 듯 이 Chunk 는 열 에 따라 데 이 터 를 구성 하고 계산 하 는 과정 에서 도 열 에 따라 계산 할 수 있 습 니 다. 그러면 한 열 에 있 는 데 이 터 를 Cache 에 오래 머 무 르 게 하고 Cache Miss 율 을 줄 일 수 있 으 며 CPU 의 pipeline 도 충분히 이용 할 수 있 습 니 다. 이 부분 은 후속 소스 분석 글 에서 상세 하 게 소개 할 것 입 니 다.여 기 는 더 이상 펼 쳐 지지 않 습 니 다.
  • 메모리 모니터링 과 제어 가 더욱 편리 합 니 다. Chunk 에 서 는 인 터 페 이 스 를 사용 하지 않 았 습 니 다. Chunk 가 현재 사용 하고 있 는 메모리 의 크기 를 직접 가 져 올 수 있 습 니 다. 구체 적 으로 이 함 수 를 볼 수 있 습 니 다. Memory Usage. TiDB 메모리 제어 에 대해 서도 후속 글 에서 자세히 소개 하 겠 습 니 다. 여기 도 더 이상 펼 치지 않 습 니 다.
  • 3.  신 구 실행 프레임 성능 대비
    새로운 실행 프레임 워 크 를 사용 한 후에 OLAP 형식 문장의 실행 속도, 메모리 사용 효율 이 크게 향상 되 었 습 니 다. TPC - H 대비 결과 성능 이 양 적 으로 향상 됐다.
    지은 이

    좋은 웹페이지 즐겨찾기