Impala 옵티마이저는 행 수와 컬럼별 distinct 수를 보고 조인 순서와 조인 방식(broadcast 인지 shuffle 인지)을 정한다. 통계가 없으면 큰 테이블을 broadcast 하려다 메모리를 터뜨리는 계획이 나온다. 메모리 부족이 잦다면 통계부터 확인한다.
SHOW TABLE STATS db.tbl;
SHOW COLUMN STATS db.tbl;
#Rows 가 -1 이면 통계가 없는 것이다.
COMPUTE STATS db.tbl;
COMPUTE INCREMENTAL STATS db.tbl;
COMPUTE INCREMENTAL STATS db.tbl PARTITION (bse_dt='20241206');
COMPUTE STATS 는 테이블 전체를 스캔한다. 파티션이 많고 매일 일부만 바뀌는 테이블이라면 COMPUTE INCREMENTAL STATS 로 바뀐 파티션만 계산하는 편이 싸다.
증분 통계는 공짜가 아니다. 파티션마다 중간 통계를 메타스토어에 저장하는데, 그것이 PARTITION_PARAMS 테이블의 impala_intermediate_stats_chunk1, ...chunk2 항목이다. 파티션과 컬럼이 많으면 이 값이 수십~수백 MB 로 불어나 메타스토어와 catalogd 메모리를 함께 압박한다. impalad 에는 테이블당 증분 통계 크기 상한 플래그(inc_stats_size_limit_bytes)가 있고, 넘으면 통계 갱신이 거부된다.
메타스토어 테이블에서 직접 DELETE 하지 않는다. PARTITION_PARAMS 는 다른 메타데이터와 엮여 있고, catalogd 캐시와도 어긋나게 된다. 반드시 SQL 로 지운다.
DROP INCREMENTAL STATS db.tbl PARTITION (bse_dt='20241206');
DROP STATS db.tbl;
DROP STATS 는 테이블의 모든 통계를 지운다. 지운 뒤에는 다시 계산해야 조회 계획이 나빠지지 않는다.
컬럼 수가 많은 테이블은 증분 통계를 아예 쓰지 않고, 필요한 컬럼만 대상으로 전체 통계를 돌리는 쪽이 낫다.
COMPUTE STATS db.tbl (id, bse_dt, amt);
표본으로 근사해도 되는 큰 테이블은 샘플링을 쓴다.
COMPUTE STATS db.tbl TABLESAMPLE SYSTEM(10);
원인은 대개 테이블 크기가 아니라 구조다. 파티션 수천 개 · 컬럼 수백 개 조합이면 메타데이터 처리에만 시간이 간다. 순서대로 확인한다.
증분 통계를 쓰면서 전체 파티션을 대상으로 돌리고 있지는 않은지, 작은 파일이 지나치게 많지는 않은지, 통계가 정말 필요한 컬럼이 몇 개인지 본다. Kudu 테이블은 HDFS Parquet 보다 통계 계산이 느린 편이므로 주기를 길게 잡는다.
Impala 와 Hive 는 같은 메타스토어를 쓴다. Impala 에서 DROP STATS 하면 Hive 쪽 numRows 도 사라지고, Hive 에서 ANALYZE TABLE 로 채운 통계는 Impala 가 보게 된다. 다만 컬럼 통계의 형식이 완전히 같지는 않아, 한쪽에서 만든 통계를 다른 쪽이 최적으로 쓰지 못하는 경우가 있다. 주로 쓰는 엔진에서 통계를 관리한다.
Spark 로 적재한 파티션은 통계가 갱신되지 않는다. 적재 후 COMPUTE INCREMENTAL STATS ... PARTITION (...) 을 배치에 넣는다.