[Clickhouse] Clickhouse Cloud로 시작해보기

클릭하우스는 OLAP 전용 데이터베이스 시스템 서비스다. 2016년에 나왔다.
오픈소스라서 직접 깔아다 쓸 수도 있고, 오픈소스그룹에서 관리하는 managed 서비스를 쓸 수도 있다.
여기서는 서비스를 쓰겠다.

보통의 상용 RDB들은 OLTP에 최적화되어있어서, 복잡한 OLAP 쿼리들은 느릴 뿐더러 메인서비스에 과부하까지 줄 수가 있다. 그래서 여러가지 OLAP를 수행할 필요가 있을 때는 데이터만 복사해서 좀더 전문적인 DB에 넣고 돌리곤 하는데, 이게 딱 그걸 위한 서비스다.
row-base인 일반 RDB와 다르게 column-base의 구조를 갖고 있고, MergeTree라는 구조로 인덱스를 관리한다.

페타바이급의 데이터도 1초 안에 처리하는데 성공했다고 한다..

같은 포지션의 다른 메이저 서비스로는, GCP BigQuery, AWS RedShift 등이 있다.
벤치마크 좀 찾아보니까 빅클라우드 기술들에도 꿇리지 않는 것 같다.




비용

서버리스 시스템이라서 딱 쓰는만큼만 비용을 뜯어간다.
비용은 리전마다 다르고, 스토리지와 컴퓨팅 2가지 방식으로 뜯는다.

여기서 볼 수 있다.
https://clickhouse.com/pricing#resource-billing

추정치를 제공해주기로는, 최소한 달에 300달러 정도는 생각해줘야 하지 싶다.

https://clickhouse.com/docs/en/manage/billing/

처음 가입하면 2주동안 쓸 수 있는 테스트용 크레딧을 300달러쯤 준다.




시작해보기

가입하면 어느 리전에 깔 것인지를 먼저 물어볼 것이다.

AWS외에도 GCP와 Azure 아이콘도 있는데, 저 둘은 지원예정이고 지금은 안된다. AWS만 가능하다.


게다가 리전도 좀 부족하다...
한국에서는 싱가포르가 그나마 빠르지 않을까 싶다.


아이피 접근 어떻게 할것인지를 묻는데, 나는 그냥 anywhere로 다 열겠다.


그럼 비밀번호 한번 알려주고

대시보드에 들어가질 것이다.




콘솔 접속하기

클릭하우스는 전용 클라이언트를 제공하는데, 그냥 웹콘솔을 쓸 수도 있다.
들어갈 인스턴스에 connect 누르고

밑에 connect to SQL console을 누른다.

그럼 이런식으로 창이 뜰 것인데,

우상단에 패스워드 쳐주고

쿼리를 작성해준다음에

Run 버튼을 누르면 결과를 확인할 수 있다.




신택스

clickhouse는 친숙한 SQL 스타일의 쿼리 신택스를 제공한다.
타입같은게 좀 다르긴 한데, 크게 다르지는 않다.

DB 만들고

테이블 만들고

삽입하고

조회하면서 쓰면 된다.




빅데이터 다뤄보기

clickhouse 튜토리얼 가이드에서 제공하는 데이터를 활용해서 간단한 성능테스트를 좀 해보겠다.

우선 테이블 하나 만들고

CREATE TABLE trips
(
    `trip_id` UInt32,
    `vendor_id` Enum8('1' = 1, '2' = 2, '3' = 3, '4' = 4, 'CMT' = 5, 'VTS' = 6, 'DDS' = 7, 'B02512' = 10, 'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14, '' = 15),
    `pickup_date` Date,
    `pickup_datetime` DateTime,
    `dropoff_date` Date,
    `dropoff_datetime` DateTime,
    `store_and_fwd_flag` UInt8,
    `rate_code_id` UInt8,
    `pickup_longitude` Float64,
    `pickup_latitude` Float64,
    `dropoff_longitude` Float64,
    `dropoff_latitude` Float64,
    `passenger_count` UInt8,
    `trip_distance` Float64,
    `fare_amount` Float32,
    `extra` Float32,
    `mta_tax` Float32,
    `tip_amount` Float32,
    `tolls_amount` Float32,
    `ehail_fee` Float32,
    `improvement_surcharge` Float32,
    `total_amount` Float32,
    `payment_type` Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4),
    `trip_type` UInt8,
    `pickup` FixedString(25),
    `dropoff` FixedString(25),
    `cab_type` Enum8('yellow' = 1, 'green' = 2, 'uber' = 3),
    `pickup_nyct2010_gid` Int8,
    `pickup_ctlabel` Float32,
    `pickup_borocode` Int8,
    `pickup_ct2010` String,
    `pickup_boroct2010` String,
    `pickup_cdeligibil` String,
    `pickup_ntacode` FixedString(4),
    `pickup_ntaname` String,
    `pickup_puma` UInt16,
    `dropoff_nyct2010_gid` UInt8,
    `dropoff_ctlabel` Float32,
    `dropoff_borocode` UInt8,
    `dropoff_ct2010` String,
    `dropoff_boroct2010` String,
    `dropoff_cdeligibil` String,
    `dropoff_ntacode` FixedString(4),
    `dropoff_ntaname` String,
    `dropoff_puma` UInt16
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(pickup_date)
ORDER BY pickup_datetime;

샘플데이터를 때려박아준다.
클릭하우스는 S3 기반의 데이터를 읽어서 넣어주는 기능을 제공한다.

INSERT INTO trips
SELECT * FROM s3(
    'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_{1..2}.gz',
    'TabSeparatedWithNames', "
    `trip_id` UInt32,
    `vendor_id` Enum8('1' = 1, '2' = 2, '3' = 3, '4' = 4, 'CMT' = 5, 'VTS' = 6, 'DDS' = 7, 'B02512' = 10, 'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14, '' = 15),
    `pickup_date` Date,
    `pickup_datetime` DateTime,
    `dropoff_date` Date,
    `dropoff_datetime` DateTime,
    `store_and_fwd_flag` UInt8,
    `rate_code_id` UInt8,
    `pickup_longitude` Float64,
    `pickup_latitude` Float64,
    `dropoff_longitude` Float64,
    `dropoff_latitude` Float64,
    `passenger_count` UInt8,
    `trip_distance` Float64,
    `fare_amount` Float32,
    `extra` Float32,
    `mta_tax` Float32,
    `tip_amount` Float32,
    `tolls_amount` Float32,
    `ehail_fee` Float32,
    `improvement_surcharge` Float32,
    `total_amount` Float32,
    `payment_type` Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4),
    `trip_type` UInt8,
    `pickup` FixedString(25),
    `dropoff` FixedString(25),
    `cab_type` Enum8('yellow' = 1, 'green' = 2, 'uber' = 3),
    `pickup_nyct2010_gid` Int8,
    `pickup_ctlabel` Float32,
    `pickup_borocode` Int8,
    `pickup_ct2010` String,
    `pickup_boroct2010` String,
    `pickup_cdeligibil` String,
    `pickup_ntacode` FixedString(4),
    `pickup_ntaname` String,
    `pickup_puma` UInt16,
    `dropoff_nyct2010_gid` UInt8,
    `dropoff_ctlabel` Float32,
    `dropoff_borocode` UInt8,
    `dropoff_ct2010` String,
    `dropoff_boroct2010` String,
    `dropoff_cdeligibil` String,
    `dropoff_ntacode` FixedString(4),
    `dropoff_ntaname` String,
    `dropoff_puma` UInt16
") SETTINGS input_format_try_infer_datetimes = 0

이러면 샘플데이터를 잘 넣어줄 텐데, 150MB짜리라서 조금 걸릴 수도 있다.

다 들어갔다면 조회가 가능할 것이다. 삽입은 느리지만 조회는 매우 빠르다.

400만개 정도가 들어있는데도

이런 일반적으로 느린 쿼리도 1초 미만에 수행이 되고

이런 헤비한 쿼리도 매우 빠르게 실행한다.

SELECT
    pickup_ntaname,
    toHour(pickup_datetime) as pickup_hour,
    SUM(1) AS pickups
FROM trips
WHERE pickup_ntaname != ''
GROUP BY pickup_ntaname, pickup_hour
ORDER BY pickup_ntaname, pickup_hour

깊게 써보진 않았지만 잘 만들긴 잘 만든 것 같다.



참조
https://clickhouse.com/docs/en/sql-reference/statements/select/