본문 바로가기
SingleStoreDB/사례연구

[사례 연구, PandoraTV] 수 천억 행의 쿼리를 위한 실시간 대쉬보드 구축

by 에이플랫폼 [Team SingleStore Korea] 2020. 1. 8.

개요

​2016년에는 특정 비즈니스 문제를 해결하기 위한 데이터 저장소와 기반 기술로 SingleStore를 선택했습니다. 이 포스트에서 다음을 내용을 보고자 합니다.

  • 비즈니스 문제
  • 기존 시스템
  • 비즈니스 및 기술 요구 사항
  • 검토 대상 솔루션
  • SingleStore 개요
  • SingleStore 구현 방법
  • 데이터 전략: 컬럼스토어 vs. 로우스토어
  • 하드웨어 세부 정보
  • 다양한 학습 경험
  • 요약

 

비즈니스 문제

​해결책을 찾는 첫 번째 단계는 문제를 명확하게 정의하는 것입니다. 그 문제를 해결할 수 있는 방법을 찾는 것이 아니라, 그 문제를 해결할 수 있는 가장 좋은 방법을 찾는 것이 목표였습니다.

우리가 해결하려고 했던 것은 광고 판매 팀이 현재 광고 캠페인과 이전 광고 캠페인에 대한 데이터를 볼 수 있게 대쉬보드를 제공하는 것이었습니다. 물론 많은 기술적인 세부 요구 사항들이 있었지만, 비즈니스 관점에서 보면, 핵심 성공 기준은 단순히 사용자가 쉽고 빠르게 사용할 수 있는 "대쉬보드 구축"이었습니다.

기존 시스템

​이 프로젝트가 시작되었을 때, 우리는 이미 회사 전체의 다양한 팀들이 매일 사용하는 시스템을 가지고 있었습니다. 많은 프로젝트의 경우와 마찬가지로, 어느 순간에는 순간의 요구 조건에 맞는 구체적인 니즈를 해결했지만, 변화하는 요구사항과 새로운 기능을 따라잡기가 점점 더 어려워졌습니다. 시간이 흐르면서 한계와 단점은 더 명확해지고 영향을 더 받게 되었습니다.

기존 시스템의 가장 큰 한계들 중 일부는 아래와 같습니다.

  • 새로운 데이터가 가용하게 되기까지 2일의 지연이 있었습니다. 월요일에 대한 답변은 수요일에나 가능했습니다.
  • 가장 어렵고 꼭 필요한 쿼리에 대한 결과는 마트(Mart) 형태로 사전에 계산되어야 했습니다. 이는 쿼리 성능에는 매우 좋았지만, 새로운 쿼리나 기존 쿼리의 약간의 변화도 쉽지 않아 상당히 경직된 사용자 경험을 초래했습니다.
  • 성능에 대해 우려 사항이었습니다. 대규모 Hadoop 클러스터에서 새로운 24시간 데이터를 지속적으로 관리하는 데 최대 20시간이 걸렸습니다. 데이터 셋이 계속 증가함에 따라 하루 분량의 데이터를 처리하기 위해 점점 더 많은 시간이 필요하게 되었습니다.

비즈니스 및 기술 요구 사항

​요구 사항들은 특별한 순서가 없이 아래에 열거하였습니다. 이 프로젝트가 시작될 때, "X솔루션을 보셨습니까? 데이터를 저장할 수 있는 방법이며 매우 훌륭합니다."라고 하면 여러 가지 "X" 솔루션들이 올라왔습니다. 어떤 경우에는 X 솔루션을 검토했지만, 어떤 경우에는 그렇게 하지 않았습니다. 요구 사항 리스트에 대해 어떤 데이터 스토리지 선택이 잘 되고 어떤 것이 지원을 하지 않는지 쉽게 확인할 수 있었습니다. 그 솔루션이 아파치 인큐베이터 프로젝트라고요? 우리는 그것을 사용하지 않을 것입니다. 클러스터를 확장하려면 전체 작업이 몇 시간이나 며칠 동안 오프라인 상태여야 합니다. 그렇게 하지 않을 것입니다. 컬럼 데이터 저장소로서 쿼리를 빠르게 처리하지만 새로운 데이터를 표시하려면 컬럼 인덱스를 다시 구성해야 한다고 생각하십니까? 아닙니다.

실시간 쿼리를 통한 결과 제공

미리 정의된 특정 쿼리에 대한 답변을 사전 계산하는 대신, 1초 이내에 실시간 쿼리를 지원할 수 있을 만큼 충분히 빠른 데이터 저장소를 원했습니다.

가능한 한 빨리 새로운 데이터를 이용할 수 있어야 합니다.

우리는 새로운 데이터를 2일보다 훨씬 더 빨리 이용할 수 있기를 원했습니다. 일부 데이터 저장소(솔루션)는 미리 고정 답변를 계산하여 쿼리 속도를 해결했습니다. 이는 요구사항 중 "사전 계산된 답변 안됨"으로 부적합했습니다. 우리는 새로운 데이터가 도착하는 주기, 즉 야간 작업을 기다리는 것으로 부터 벗어나서 대쉬보드로 결과를 보고 싶었습니다. 향후 UI에 표시할 새 데이터를 갖고 있을 때 실시간 쿼리도 더 빠를 것입니다.

2 년간의 원시 클릭 데이터와 노출 데이터 지원

2년의 기간은 가장 긴 비즈니스 요구 사항을 초과하기 시작하였습니다. 초기 계획은 스토리지 증가(컬럼 데이터)와 성능 저하 (읽기/쓰기 모두)에 대한 우려로 인해 2 년이상의 데이터를 롤링 윈도우를 유지하는 것이었습니다. 이 요구사항은 "수십억 개의 행"과 "수 테라바이트의 데이터"로 해석이 되었습니다. "2년"이라는 수치는 상당히 보수적인 것으로 판명되었습니다. 현재는 성능에 영향을 미치지 않고 스토리지가 많이 남아있는 상태에서 4년 동안 누적된 데이터에 접근하고 있습니다. (칼럼 데이터의 경우 85-90% 디스크 압축)

속도가 빨라야

확고한 목표로 100억 행의 데이터에 대해 1초미만의 쿼리 응답을 원했습니다. 일부 데이터 저장소들은 "빠르다"거나 "Y보다 X배 빠르다"(Presto가 Hive보다 100배 이상 빠를 수 있다)고 주장하지만, 실제 숫자는 얼마인가? 예를 들어, 테이블에 100억 행이 있는 경우 쿼리를 실행하고 결과를 얻는 데 걸리는 시간은? 많은 "빠른" 데이터 저장소들은 "몇 초"에서 몇 분(또는 그 이상)까지 응답 속도를 제공합니다. 2시간 Hive 쿼리보다 100배 빠르다는 것은 대쉬보드를 클릭하는 사용자를 만족시키지 못합니다.

제품 성숙도

이것이 어려운 요구사항은 아니겠지만, 우리가 편안하게 느끼는 것보다 훨씬 더 실험적인 옵션들이 혼합되어 있다는 것은 명백했습니다. 왜 이것이 중요했는가? 이 프로젝트의 기반 솔루션으로 입증되지 않은 기술에 의존하고 싶지 않았습니다. 지금까지 해보지 못한 일들을 시도하는 잡초 속으로 곧장 뛰어들기 보다는, 이상적으로 우리 것과 비슷한 규모로 실제 생산 용도로 사용하는 것을 선택하는 것이 중요하다고 생각했습니다. 어떤 프로젝트들은 개방형 타임라인뿐만 아니라 리스크 대 보상의 트레이드오프를 감당할 수 있겠지만 우리는 그럴 수 없었습니다. 그럼에도 우리는 확신을 갖고 대문 밖으로 나갈 수 있는 무언가를 원했습니다.

내부 채택에 대한 최소한의 장벽

이 요건은 팀에 새로운 기술을 도입하는 현실을 다루었습니다. 몇몇 옵션은 흥미로운 솔루션처럼 보였지만 전혀 독특하고 생소한 쿼리 언어를 가지고 있었습니다. 일부 옵션은 데이터베이스 드라이버에 상당한 제한이 있었습니다. 이상적으로, 우리는 표준 SQL을 지원하고 많은 데이터베이스 드라이버를 사용할 수 있는 것으로 끝나게 될 것입니다.

24 x 7 지원

문제가 발생할 경우, 문제를 이해하고 해결책을 찾고 해결 방법을 구현하기 위해 자체 엔지니어에게 의존해야 하는가? 하드웨어 문제, 운영 문제, 소프트웨어 버그, 잘못된 구성, 사용자 실수... 우리는 경험을 통해 시간이 흐르면서 뭔가 잘못될 것이라는 것을 알았습니다. 우리가 모르는 것은 무얼을, 언제 또는 어떻게 그것을 고칠 것인가입니다. 즉각적인 도움에 대한 옵션이 있나?

확장 가능해야 하는 요구

데이터 셋이 증가하고 사용 패턴이 변화함에 따라 용량을 늘릴 수 있는 방법이 필요했습니다. 이는 스토리지 용량을 늘리기 위해 디스크를 더 추가하거나 쿼리 성능을 유지하기 위해 더 많은 컴퓨팅을 추가하는 것을 의미할 수 있습니다.

숨겨진 비용에 대한 고려

우리는 선불 비용만으로 선택을 하는 것이 아니라는 것을 확신하고 싶었습니다. 많은 면에서 훌륭한 "비용 無" 선택사항들이 몇 개 있었지만, 분명히 우리가 엔지니어가 학습하고, 이해하고, 구현하고, 운영하고, 유지하고, 문제 해결과 이슈를 고치는데 오랜 시간(달?, 연?)에 걸쳐 급여를 지불해야 했을 것입니다. 이들에게는 소프트웨어 자체가 무료임에도 불구하고 사실 많은 비용이 들 것이라는 것을 쉽게 알 수 있었습니다. 우리는 우리가 무엇을 선택하든, 시스템을 운영하고, 시스템을 설계하고, 성능을 이해하고 측정하고, 문제를 해결하는 것과 같은 것들을 할 필요가 있다는 것을 알고 있었습니다. 만약 그것이 그러한 것들을 가속시킬 수 있다면 우리는 기꺼이 돈을 미리 쓸 것입니다.

검토 대상 솔루션

​우리의 요구 사항에 따라, 우리는 첫 번째 그룹을 최종 후보 솔루션은 3개로 좁혔습니다. 이들 각 최종 후보들은 우리의 모든(또는 거의 모든) 요구 사항을 해결했습니다.

RedShift

기능과 성능은 뛰어났지만, 소요 비용은 상당한 마이너스 요소였습니다. 3년 동안, 컴퓨팅/메모리/디스크가 유사한 사내 하드웨어를 SingleStore나 CitusDB와 함께 구입하는 것에 비해 RedShift를 추구하는 데 몇 배나 더 많은 비용이 들 것입니다. 또한, RedShift를 사용하는 것은 아마존 데이터 센터로 데이터를 전송하는 또 다른 장애물을 극복하는 것을 의미했을 것입니다.

CitusDB

우리가 찾고 있는 대부분의 솔루션을 점검했지만, 다른 최종 후보자들만큼 완벽하지는 않았습니다. 우리는 2016년 상반기에 - 2년 이상 동안 이 평가를 수행했고, 그 이후로 CitusDB가 크게 개선될 수 있다는 확신이 있을 수 있을 것입니다. 그들은 훌륭한 팀과 함께 올바른 방향으로 향하고 있는 것처럼 보였지만, Pandora가 찾고 있는 요건을 맞추기 위해서는 시간이 더 필요했습니다.

SingleStore

이는 우리가 해결하고자 하는 문제를 해결하기 위한 기능, 성능 및 유연성의 적절한 조합을 제공했습니다.

아래는 도중에 탈락한 원래 30개의 경쟁사들 중 몇입니다. 분명히, 각각의 제품은 장단점과 함께 사용하려고 의도한 것입니다. 우리의 평가 단계는 각각의 선택사항을 우리의 요구조건에 적합하게 점검하기 시작했습니다. 아래에서는 사용 시나리오의 부정적인 내용만 호출되는 것을 볼 수 있습니다. 이는 이러한 데이터 스토리지 옵션 중 어떤 것도 일반적으로 나쁘다고 묘사하는 것을 의미하지는 않습니다.

 

Google BigQuery는 읽기 전용 데이터, SQL 조인의 제한과 Google 스토리지가 필요한 여러 가지 이유로 인해 배제되었습니다. 또한 BigQuery는 모든 데이터 셋(소규모 또는 대규모)에 대해 1초 미만의 쿼리를 제공하도록 만들어지지 않았습니다

Apache Impala는 성능상의 이유로 배제되었습니다. 한 데이터 포인트는 15TB 데이터 세트에서 동시 사용자 10명에 대한 쿼리 응답 시간을 12초로 보여주었습니다.

 

Kylin은 새로운 데이터를 위해 데이터 큐브를 미리 계산하기 위해 오프라인 처리를 해야 하기 때문에 배제되었습니다.

 

Apache Phoenix는 성능상의 이유로 배제되었습니다. 피닉스 웹사이트에 발표된 성능 결과는 1,000만 행의 테이블에서 몇 초의 쿼리 시간이 요구된다고 논의되었습니다.

 

VoltDB는 비용에서 배제되었습니다. 그것은 시스템 메모리에 전적으로 의존하기 때문에, 우리는 수천억 행(테라바이트)의 데이터를 저장할 수 있는 충분한 메모리를 갖기 위해 하드웨어에 많은 돈을 투자해야 했을 것입니다. 또한 표준 SQL이 아니며(foreign Key나 auto-increment 같은 기능 지원 않함), 모든 것이 스토어드 프로시저입니다.

SingleStore에 관하여

​SingleStore는 2011년 에릭 프레키엘과 니키타 샴구노프에 의해 설립되었습니다. SingleStore 데이터베이스는 2013년에 처음 제공되었습니다. 고객으로는 Akamai, Comcast 그리고 Uber 등 이 있습니다. 여기에서 해당 고객에 대해 자세히 알아보실수 있습니다. SingleStore는 엔터프라이즈 라이센스로 24x7 기술 지원을 제공합니다. 자세한 정보와 배경을 위해, SingleStore의 이 게시물은 SingleStore가 무엇이고 어떻게 작동하는지 개략적으로 보여줍니다. 또한 Wikipedia에 몇 가지 좋은 개요 정보를 가지고 있습니다.

SingleStore 구현 방법

​우리의 목표는 여러 다양한 소스의 데이터를 단일 데이터 스토어로 통합하는 것이었습니다. 이를 위해 Hive, Postgres와 데이터 파일에서 데이터를 얻기 위해 몇 가지 다른 수집 경로를 만들었습니다. 이러한 데이터 소스 중 하나는 앞서 언급한 "100억 행의 데이터"로 구성되었으며, 즉시 해당 데이터에 대한 쿼리 성능을 극대화할 수 있는 솔루션을 구축하는데 집중했습니다.

우리는 SingleStore 팀과 직접 협력하여 여러 가지 중요한 단계를 파고 들었습니다. 이것은 우리에게 시간을 절약하는데 있어서 매우 귀중한 것이었습니다. 우리는 초기 논의부터 테스트 클러스터 구축, 프로덕션 클러스터 구축과 완전 라이브에 이르기까지 SingleStore 팀과 계속 협력했습니다. 우리가 한 일들 중 일부는 다음과 같습니다.

  • 실제 샘플 데이터 셋 구축 방법
  • SingleStore의 작동 방식 이해(일반적인 사항과 우리의 실데이터 환경 모두에 대해)
  • 다양한 하드웨어 구성과 클러스터 설정에 따라 상황이 어떻게 변하는지 이해
  • 최적의 쿼리 성능 파악
  • 하드웨어 문제 발생 시 최고의 이중화를 제공하기 위해 클러스터를 구축하고
  • 구성 하는 방법 이해
  • 쿼리와 클러스터 성능을 측정하고 평가하는 방법 학습
  • 클러스터 관리에 대한 기본적 학습과 중점적으로 모니터링해야 할 "Red flags "에
  • 대해 학습(Support 팀으로 바로 에스컬레이션해야 하는 사항)

​​

시간이 지남에 따라, 우리는 컬럼 데이터 성능에만 초점을 맞춘 적절한 테스트 클러스터를 이해하고 구축할 수 있었습니다. Rowstore 테이블은 columnar보다 여러 장점(속도뿐 아니라)이 있지만 메모리 사용량의 영향은 중요한 요소였습니다. Rowstore 테이블은 클러스터 메모리에 직접 저장되는 반면 Columnar 테이블은 주로 Disk에 저장됩니다. 고려해야 할 많은 요인들이 있지만, 오랜시간동안 우리가 정의한 간단한 규칙은 "테이블이 10억 줄 미만일 경우, Rowstore로 시작하고, 10억 개 이상이면 Columnstore로 시작하라"입니다.

우리는 최대 데이터 셋 용으로 write 성능을 극대화하는 경로를 포함하여 몇 개의 데이터 수집 경로를 구축했습니다. 테스트 클러스터에서는 데이터를 빠르게 write 전에 한 대의 머신에서 초당 150,000개의 insert를 몇 시간 동안 컬럼 테이블에 유지할 수 있었습니다. 여러 머신으로 클러스트에 write를 하면 초당 500,000 개의 insert를 유지할 수 있습니다. 1초당 1M의 속도는 가능했지만 다른 곳에서는 부하를 발생시켰습니다. 이는 예를 들어 100억 행의 테스트 데이터 셋을 사용하여 성능 테스트를 수행하고, 변경 사항(구성, 테이블 정의, 클러스터 설정 등)을 변경하고, 경과한 5-6시간 내에 동일한 100억 행을 다시 로드한 다음, insert 성능 테스트를 수행할 수 있음을 의미했습니다.

우리가 오랜시간 동안 개발한 또 다른 기술은 수천억 행의 데이터에 대해 새 대쉬보드를 구동하기 위해 빠른 write 수행과 1초 미만의 고성능 쿼리를 만드는 것이었습니다. 모든 퍼포먼스 튜닝과 마찬가지로 이것은 예술과 과학이 혼합 된 것과 같이 작업 속도가 빨라졌습니다. 고맙게도, 문제에 봉착 될 때마다 튜닝/조정 방법에 대한 정보를 SingleStore에 문의 할 수 있었습니다.

Data 전략 (Columnstore vs. Rowstore)

​SingleStore는 테이블별로 정의된 Columnstore나 Rowstore의 데이터 저장 방법을 지원합니다 ( Rowstore에는 normal과 reference 테이블의 2가지 변수을 갖고 있음). 어떤 테이블은 Columnstore로, 다른 테이블은 Rowstore로, 그리고 어떤 테이블은 레퍼런스 테이블로 정의할 수 있다는 것은 강력한 기능입니다. 데이터 정렬과 구성 방법에 유연성을 제공하며 쿼리 성능, 메모리 사용량, 디스크 사용량, 네트워크 트래픽 간에 트레이드오프를 선택할 수 있습니다. 따라서 주어진 테이블에 대해 당신은 어떤 것을 고르시겠습니까? 이에 대한 주제에 대해 SingleStore 문서에 자세하게 다루고 있습니다. 추가로 아래에서는 우리와 관련이 있는 몇 가지 사항을 포함하여 설명드리려고 합니다.

​​

레퍼런스 테이블(Reference Table)

​테이블이 수백이나 수천 행으로 충분히 작다면 레퍼런스 테이블은 훌륭할 수 있습니다. 레퍼런스 테이블의 데이터는 클러스터의 노드 전체에 분산되지 않고 각 노드에는 전체 테이블의 전체 복사본이 있습니다. 클러스터에 32개의 노드가 있는 경우 해당 테이블의 복사본이 32개가 있을 것입니다. 테이블의 전체 복사본을 각 노드에 보관함으로써 쿼리 실행 속도를 높일 수 있습니다.

레퍼런스 테이블 사용은 추가 시스템 메모리 사용 비용입니다. 이런 트레이드 오프는 작은 테이블의 경우 개별 노드가 더 이상 해당 테이블에 대해 다른 노드에 질문하지 않아도 되므로 향상된 쿼리 성능의 가치가 있을 수 있습니다. 그러나 클러스터 전체 메모리 사용량은 빠르게 증가됩니다.

​Columnar 삭제와 업데이트

​모든 CRUD 작업은 칼럼 테이블에서 지원되지만, 칼럼 데이터에 대한 각 작업 수행의 의미를 이해하는 것이 중요합니다.

Insert와 Read는 일반적으로 빠릅니다. SingleStore는 쓰기를 빠르게 처리하고 또한 새로운 행을 바로 읽을 수 있게 하는데 매우 훌륭합니다. 각 칼럼 테이블에는 새로운 데이터가 축적되는 더 작고 숨겨진 Rowstore 테이블이 있습니다. 이를 통해 Disk I/O에서 대기 시간없이 쓰기가 빠르게 이루어 지게 합니다. 이 두 테이블를 혼합하여 사용하면 Read 속도도 빨리 제공될 수 있습니다. 이것은 1,000만개의 행을 컬럼 테이블에 쓸 수 있게 하고 그 행의 쿼리 결과를 거의 즉시 볼 수 있게 합니다. 읽기 성능을 위해 SingleStore는 코어 및 초당 수백만 개의 행을 쿼리할 수 있습니다. 수천억 줄의 행이 있는 테이블 의 읽기 및 쓰기 성능은 매우 빠르기 때문에 마치 마술처럼 느껴집니다.

Update와 Delete는 다른 방식으로 작동하며 상당히 느립니다. 이는 컬럼 테이블이 주로 디스크에 저장되므로 행에 대한 모든 변경은 디스크 I/O를 포함한다는 것을 고려하면 타당한 결과입니다. Fact형 데이터에 컬럼 테이블을 사용하는 것은 대량의 데이터를 처리하고 읽기 쿼리를 매우 빠르게 처리할 수 있기 때문에 매우 적합합니다. 컬럼 삭제 및 업데이트를 최소(또는 거의 없게)로 유지함으로써 클러스터는 더 많은 CPU와 디스크 I/O를 사용하여 읽기 쿼리를 처리 할 수 있습니다. 자주 업데이트나 삭제등 데이터를 변경하기 위해 컬럼 테이블을 사용하려는 의도라면 한 걸음 뒤로 물러서서 다른 방식으로 문제에 접근하는 것이 좋을 것입니다.

​​

읽기 vs 쓰기(Read vs. Write)

​읽기와 쓰기 사이에서 대쉬보드를 강화시키기위해 필요한 것이 빠른 쓰기보다 빠른 읽기가 더 중요하다는 것을 알았습니다. 이 점은 매우 자주 표출되지는 않았지만 때때로 어떻게 진행할지 결정하는 데 도움이 되었습니다.

​​

인덱스(Index)

​Rowstore 테이블은 고유한 인덱스를 포함하여 하나 이상의 인덱스를 지원합니다. 컬럼 스토어 테이블은 하나 이상의 인덱스를 가질 수 없으며, 불행히도 고유성(uniqueness)을 강제할 수 없습니다.(7.0이후 부터는 여러 개의 인덱스를 갖을 수 있음) 데이터 사용량에 따라 여러 개의 인덱스와 고유한 인덱스가 필요할 수 있으며, 이 경우 Rowstore를 사용하는 것이 이미 결정되어 있을 수 있습니다. 우리의 가장 큰 테이블을 위해, 우리는 성능을 위해 추가 인텍스 뿐만이 아닌 고유한 인덱스를 사용할 수 있었지만 그것들 없이 그럭저럭 지낼 수 있었습니다.

​​

시스템 메모리

​"좋다, 빠르다, 싸다" 이중 두 개를 고르면, 균형있는 결과를 확실히 얻을 수 있습니다.

Rowstore 테이블은 "좋고 빠른" 선택이고 어느 테이블을 선택해야 할지 잘 모른다고 하면 훌륭한 출발점이 될 수 있습니다. 충분한 양의 RAM을 사용하면 이론적으로 모든 데이터를 Rowstore에 넣을 수 있고 사용자 컬럼 테이블은 절대 사용하지 않아도 되지만 먼저 고용량 메모리가 장착된 하드웨어 구매를 해야 합니다.

컬럼 테이블은 "빠르고 값싼" 선택입니다. 충분한 컴퓨팅을 사용할 수 있는 상태에서 읽기 및 삽입은 뛰어난 성능을 발휘합니다. 그러나 업데이트와 삭제의 인덱스와 성능의 제한은 그림에서 "좋은"을 빼낸 것입니다.

하드웨어 세부 정보

​클러스터가 어떻게 사용되느냐에 따라 SingleStore 클러스터의 하드웨어에서 결정해야 할 사항이 있습니다. 우리의 하드웨어 선택은 읽기, 쓰기와 전체 디스크 용량이라는 컬럼의 성능에 중점을 두었습니다.

Read 성능

​컬럼 테이블의 읽기 성능은 사용 가능한 CPU 코어와 디스크 성능의 영향을 받습니다. 사용 가능한 CPU 코어가 너무 적 으면 빠른 디스크만으로도 빠른 읽기가 수행되지 않을 수 있습니다. 예를 들어, 동일한 디스크 설정을 가진 2대의 머신이 있는 경우 16코어 머신은 4코어 머신보다 더 빠른 컬럼 읽기를 제공합니다. 마찬가지로, 많은 가용 CPU 코어는 10,000 rpm 회전 디스크로는 확실히 느린 읽기 성능을 제공할 수 밖에 없습니다. 빠른 읽기 성능은 빠른 디스크의 쓰기 성능 뿐만 아니라 많은 CPU 코어를 요구합니다. 초기에는 서로 다른 cpu + disk 구성으로 테스트하여 SingleStore의 작동 방식에 대한 경험 쌓고 이해를 했습니다. SSD 대신 10k 드라이브를 사용하여 클러스터를 구축이 가능한가? 32 코어나 64 코어 대신 8 코어 머신을 사용할 수 있나? 이러한 변수는 성능에 어느 정도 영향을 미치나? 우리가 수행 한 테스트는 하드웨어를 결정할때 매우 중요했습니다.

​​

Write 성능

​컬럼 테이블의 쓰기 성능은 주로 디스크 쓰기 성능에 영향을 받습니다. 테스트 클러스터에서는 RAID 0(스트라이핑) 구성에서 여러 SSD 드라이브를 사용하여 이 문제를 해결했습니다. 운영 클러스터에서는 SingleStore의 권장 사항에 따라 RAID 1(데이터의 미러링 복사본)과 RAID 0(여러 Disk에 데이터를 스트라이핑하여 더 빠른 성능)의 조합인 RAID 10의 추가 하드웨어 이중화를 선택했습니다.

SingleStore는 내부적으로 어떤 이유로든 노드가 완전히 오프라인 상태가 되는 것에 대한 강력한 이중화 기능을 가지고 있습니다. 뒤에서 클러스터는 모든 물리적 호스트의 모든 노드에 걸쳐 데이터를 분산시키고 모든 데이터의 복사본을 유지합니다. 그렇게 하면 하나의 호스트가 사라지면 각 노드의 데이터는 다른 시스템의 다른 노드에서 즉시 사용할 수 있게 됩니다. 이 방법은 정말 멋집니다. 반복적인 읽기 및 쓰기를 반복하는 클러스터에서 하나의 노드를 죽였고, 쿼리 루퍼에서 실패 한 것을 본 다음 1-2초 후에 모든 것이 다시 잘 작동하는 테스트를 수행했습니다.

SingleStore는 장애 조치(failover) 작업 수행하기 위해 백그라운드에서 데이터를 복사하는 것을 포함한 많은 것을 수행합니다. 각각의 데이터는 두 곳에 있습니다. 첫번째는 마스터이고 두번째는 슬레이브입니다. SingleStore는 현재 누가 마스터인지, 누가 슬레이브인지, 마스터가 없어지면 언제 슬레이브를 승격시킬 것인지, 그리고 오래된 슬레이브가 없어지면 누가 새로운 슬레이브로 인계받을 것인지를 추적하는 등을 자동으로 관리합니다. 데이터 규모에 따라 테스트 결과 이러한 페일오버 작업이 20~30분 정도 소요되었습니다. 이 시간 동안 클러스터는 추가적인 CPU, 디스크 I/O와 네트워크를 사용하게 되어 모든 작업의 쿼리 성능이 약간 저하가 됩니다. 미러링된 RAID 구성이 없으면 단순한 드라이브 장애로 인해 페일오버 시나리오가 트리거 됩니다. RAID 10을 사용하여 드라이브 교체에 대한 경고를 트리거하는 것외의 작업을 수행하지 않도록하여 드라이브 장애를 제거했습니다.

디스크 용량

​전체 디스크 용량은 단순히 각 SSD 디스크의 크기와 양을 추가하는 것보다 더 많이 사용되었습니다. 최소한 RAID 10을 사용할 수 있도록 물리적 디스크가 4개 이상 필요했습니다. 다른 디스크 구성을 살펴보면서 다른 제약 사항도 발견했습니다. 머신 당 물리적 디스크 수가 증가함에 따라 더 큰 섀시를 사용해야 하고, 마더보드가 변경되어 다른 모든 것이 변경될 수 있습니다. 더 큰 섀시는 분명히 물리적 랙에서 더 많은 공간을 사용할 수 있는데, 이 공간을 원하지 않을 수도 있습니다. 그래서 처음에는 각 머신에 대해 많은 양의 소형 SSD를 구입함으로써 비용을 절감하는 것이 호소력이 있었지만, 물리적 디스크 수용을 위해 머신의 나머지가 바뀌면서 비용 절감 효과는 사라졌습니다. 테스트를 기반으로 데이터가 계속 증가하고 시간이 지남에 따라 총 디스크 사용량을 정확하게 예측 할 수 있었습니다. 결국 우리는 머신 당 4개의 디스크에 정착했습니다. 이로 인해 초기 비용, 향후 성장을 위한 디스크 용량과 각 머신에 대한 더 간단한 하드웨어의 균형을 안정적으로 유지할 수 있었습니다.

다양한 학습 경험

​다음은 테스트를 진행하면서 축적한 추가 학습 경험이며 특정 순서 없이 제시했습니다. 이 주제는 SingleStore의 내부 작업에 대해 조금 다루었고, 우리가 그것들에 대해 더 많이 배웠을 때 꽤 흥미로 웠습니다.

​​

Columnar 인덱스 데이터 타입

​쿼리 성능을 최적화하는 동안 컬럼 형 인덱스에 다른 데이터 유형을 사용할 때 쿼리 속도를 측정했습니다. VARCHAR, VARBINARY 및 BIGINT를 구체적으로 살펴 보았습니다.

테스트에서 숫자 컬럼 형 인덱스 키 데이터 타입 인 BIGINT가 숫자가 아닌 VARCHAR 나 VARBINARY보다 빠르다는 것을 발견했습니다. BIGINT를 ~ 0.02 초에서 측정을 했고 숫자가 아닌 두 타입 모두에서 5 배 더 긴 시간에 측정이 되었습니다. 동일한 데이터, 동일한 하드웨어, 동일한 쿼리 유일한 변수는 컬럼 인덱스 키의 데이터 타입을 변경하는 것입니다. 더 느린 VARCHAR, VARBINARY 두 옵션은 여전히 ​​빠르지만 이러한 결과는 매우 유용했습니다.

실행 계획과 플랜 캐시(Execution Plans and the Plan Cache)

​SingleStore는 표준 컴파일러 기반 데이터베이스 실행 모델을 통해 사용할 수 없는 low-level최적화를 가능하게 하기 위해 내장된 컴파일러를 사용합니다. SingleStore는 이런 최적화를 쿼리 컴파일에 사용합니다. 각 노드에서 쿼리를 처음 실행한 후에 향후 사용할 수 있도록 컴파일된 쿼리와 쿼리 플랜이 디스크에 캐시됩니다. 향후에 발생되는 모든 해당 쿼리는 컴파일된 쿼리와 실행 계획(Execution Plans)을 사용할 것입니다. 이와 관련하여 잘 작동하는 SQL을 작성하는 방법이 있지만 매번 다시 컴파일해야하는 쿼리를 실수로 작성할 수도 있습니다. 플랜 캐시를 보는 방법을 이해하면 유용합니다. 변경한 후 새로 테스트하려는 경우 캐시된 쿼리를 수동으로 제거하는 것도 유용합니다.

노드를 다시 시작할 때 캐시가 재설정됩니다. 이 기능은 클러스터의 모든 항목을 강제로 재설정하려는 경우 유용하고, 몇 개의 노드를 튕겨서 왜 작업 속도가 느린 상황이 발생하는지와 같이 혼란스러울 수 있습니다. 플랜 캐시에도 만료일이 있으므로 클러스터는 시간이 지남에 따라 주기적으로 새로운 플랜을 수립합니다. 우리는 사용자들이 주말 동안 클러스터 활동을 하지 않은 후 월요일 아침에 사무실로 돌아와 모든 것이 느리다는 것을 알게 되었을 때 이 문제에 봉착하게 됩니다. 모든 것이 예열되면 일주일 내내 좋은 성능이 유지됩니다. SingleStore의 지침에 따라 이를 수용하도록 캐시를 조정할 수 있었습니다.

OR vs IN

​우리가 발견한 시나리오 중 하나는 SQL 문에서 "IN" 조항이 아닌 "OR" 절을 사용하는 것이었습니다. 다음 두 가지 질문을 고려하시기 바랍니다.

쿼리 A : SELECT * FROM foo WHERE id = 1 OR id = 2;

쿼리 B : SELECT * FROM foo WHERE id = 1 OR id = 2 OR id = 3;

작성된 것처럼 쿼리가 매우 유사하더라도 실행 계획이 달라집니다. 우리의 사용법에서“id = 1 OR id = 2”절은 동적으로 생성되며 1에서 수십 또는 그 이상의 OR 문을 가질 수 있습니다. 각각 약간의 변형으로 인해 새로운 실행 계획이 만들어졌기 때문에 간헐적으로 속도가 느려졌습니다. 이것은 식별하는 데 시간이 걸렸습니다.

다음과 같이 IN 절을 사용하면 쉽게 해결할 수 있습니다.

쿼리 A : SELECT * FROM foo WHERE id IN (1,2);

쿼리 B : SELECT * FROM foo WHERE id IN (1,2,3);

IN 절의 다른 모든 숫자 변수와 함께 이 두 쿼리 모두 동일한 실행 계획에 도달하므로 모두 빠를 것입니다.

데이터 쏠림(Data Skew)

데이터 쏠림은 테이블의 데이터가 클러스터의 노드 간에 고르지 않게 분배될 때 발생합니다. SingleStore는 사용자가 지정한 Shard 키를 사용하여 노드 전체에 데이터를 분배하거나, 명시적으로 정의하지 않은 경우 프라이머리 키(PK)로 분배합니다. 정상적인 분산 데이터베이스는 클러스터의 각 N 노드에 약1/N의 테이블 데이터가 있어야 합니다. 데이터 쏠림을 측정하고 관찰하는 것은 우리가 최적의 샤드 키를 선택했는지를 이해하는데 유용했습니다.

​​

요약

​2016년에 새로운 광고 대쉬보드에 대한 작업을 시작했을 때 프로젝트 요구 사항을 충족할 수 있을지는 확실하지 않았습니다. 결국 해결하기 어려운 문제였습니다. 실제로 우리의 초기 조사에서는 다른 대기업들이 어떻게 이 문제를 해결했는지에 대한 질문이 있었으며 이름을 밝히지 않은 여러 유명 기업들이 우리가 이미 했던 많은 문제와 한계가 있는 일일 집계 작업(daily aggregation jobs)을 하는 것과 거의 같은 방식으로 광고 대쉬보드를 운영하는 것으로 나타났습니다. 확실히, 만약 이것이 쉬운 일이었다면 이미 끝났을 것입니다.

처음부터 우리는 적절한 데이터 스토어를 선택해야 했고 그렇지 않으면 전체 프로젝트가 성공하지 못할 것이라는 것은 매우 명백했습니다. 우리의 옵션들에 대해 집중하고 요구 사항에 따라 분야를 좁힘으로써 우리는 결국 SingleStore를 선택하게 되었습니다. 프로젝트 요구 사항, 기능 및 성능 요구 사항에 매우 잘 들어 맞았습니다. 몇 년 후, 그것들이 모두 사실로 지속되는 것도 대단했습니다.

우리가 SingleStore를 사용하여 경험을 쌓으면서, Pandora에서 잘 맞을지도 모르는 다른 데이터 프로젝트를 찾기 시작했습니다. 몇 가지 사례에서, 유망해 보이는 프로젝트가 있었지만, 더 깊은 검토를 통해 모든 것에 다 적합하지 않았습니다. (이러한 프로젝트들은 그대로 유지되거나 다른 방향으로 진행되었습니다). 다른 경우에는 프로젝트 요구 사항과 SingleStore의 강점이 서로 잘 맞아 떨어져서 SingleStore의 활용 영역은 초기 광고 대쉬보드 프로젝트외로도 확대되었습니다.

Aug 14, 2018

Kaan Erdener

 

 


출처: https://www.singlestore.com/blog/pandora/

 

Pandora Repost: Using SingleStore to Query Hundreds of Billions of Rows in a Dashboard

Pandora needed a data store and foundation for solving a specific business problem, and it chose SingleStore. Read more to learn why.

www.singlestore.com

참고: https://engineering.pandora.com/using-memsql-at-pandora-79a86cb09b57

 

Using MemSQL to Query Hundreds of Billions of Rows in a Dashboard

Overview

engineering.pandora.com

​​※ www.a-platform.biz | info@a-platform.biz