버티카 Database 통계 정보 수집
Updated:
버티카 Database 통계 정보 수집
버티카의 cost-based 옵티마이저는 쿼리 실행계획을 작성하기 위해 통계 정보에 의존한다. 통계정보가 존재하지 않거나, 오래된 통계 정보를 사용하는 경우, 최적화된 실행계획을 만들 수 없다.
버티카 옵티마이저는 다음과 같은 통계 정보를 확인해서 쿼리의 실행계획을 작성한다.
- 테이블이 파티션된 경우, 파티션의 최근 통계 정보 확인
- 테이블 레벨의 통계 정보 확인
- 파티션, 테이블 레벨의 유효한 통계 정보가 없는 경우 옵티마이저는 모든 프로젝션에 대해 균일한 데이터 값 분배 및 동일한 스토리지 사용으로 가정
통계 정보 관리
버티카는 테이블, 파티션 레벨로 통계를 수집한다.
- 테이블 레벨의 통계 - ANALYZE_STATISTICS()
- 파티션 레벨의 통계 - ANALYZE_STATISTICS_PARTITION()
통계정보 여부는 projection_columns 테이블의 staticstics_type컬럼에서 확인 할 수 있다.
ANALYZE_STATISTICS()
대상 테이블의 projection을 저장하는 모든 노드에서 데이터 샘플과 스토리지 정보를 수집하고 집계한다.
ANALYZE_STATISTICS()호출시 특정 컬럼만 지정을 하더라도 모든 테이블의 컬럼에 대한 DO_TM_TASK(‘ANALYZE_ROW_COUNT’)가 호출된다.
통계정보 수집시 대상이 되는 데이터 범위를 지정할 수 있다. default는 10%이다.
ANALYZE_STATISTICS_PARTITION()
지정된 테이블에서 파티션 범위에 대한 데이터 샘플 및 스토리지 정보를 수집하고 집계한다.
DO_TM_TASK(‘ANALYZE_ROW_COUNT’);
최소한의 통계 정보와 프로젝션에 대한 row count를 수집한다.
ANALYZE_EXTERNAL_ROW_COUNT()
EXTERNAL TABLE의 정확한 ROW COUNT를 계산한다. 옵티마이저는 이 COUNT를 사용하여 EXTERNAL TABLE에 액세스하는 쿼리를 최적화 한다.
dbadmin=> DROP TABLE IF EXISTS T;
dbadmin=> --버티카에서 실습용으로 생성 할 수 있는 VMart DB의 store.store_orders_fact 테이블로 테스트 진행
dbadmin=> CREATE TABLE PUBLIC.T AS SELECT * FROM store.store_orders_fact ;
CREATE TABLE
dbadmin=>
dbadmin=> --파티션 선언
dbadmin=> ALTER TABLE public.T PARTITION BY date_ordered::DATE REORGANIZE;
NOTICE 4954: The new partitioning scheme will produce 600 partitions
WARNING 9249: Using PARTITION expression that may result in NULL values
HINT: DML statements which produce NULL values for partition expressions will roll back
NOTICE 4785: Started background repartition table task
ALTER TABLE
dbadmin=>
dbadmin=> --통계정보 생성 확인
dbadmin=> SELECT STATISTICS_TYPE , STATISTICS_UPDATED_TIMESTAMP , PROJECTION_NAME, PROJECTION_COLUMN_NAME
dbadmin-> FROM PROJECTION_COLUMNS
dbadmin-> WHERE TABLE_NAME = 'T'
dbadmin-> ORDER BY COLUMN_POSITION;
STATISTICS_TYPE | STATISTICS_UPDATED_TIMESTAMP | PROJECTION_NAME | PROJECTION_COLUMN_NAME
-----------------+------------------------------+-----------------+------------------------
NONE | | T_b1 | product_key
NONE | | T_b0 | product_key
NONE | | T_b1 | product_version
NONE | | T_b0 | product_version
NONE | | T_b0 | store_key
NONE | | T_b1 | store_key
NONE | | T_b0 | vendor_key
NONE | | T_b1 | vendor_key
--중략
(38 rows)
dbadmin=> --실행계획 확인
dbadmin=> EXPLAIN SELECT COUNT(*) FROM T WHERE DATE_ORDERED = '2006-12-10';
QUERY PLAN
------------------------------
------------------------------
QUERY PLAN DESCRIPTION:
------------------------------
EXPLAIN SELECT COUNT(*) FROM T WHERE DATE_ORDERED = '2006-12-10';
Access Path:
+-GROUPBY NOTHING [Cost: 223, Rows: 1 (NO STATISTICS)] (PATH ID: 1)
| Aggregates: count(*)
| Execute on: All Nodes
| +---> STORAGE ACCESS for T [Cost: 222, Rows: 10K (NO STATISTICS)] (PATH ID: 2)
| | Projection: public.T_b0
| | Filter: (T.date_ordered = '2006-12-10'::date)
| | Execute on: All Nodes
--중략
dbadmin=> --테이블 레벨의 통계 정보 수집
dbadmin=> SELECT ANALYZE_STATISTICS('PUBLIC.T');
ANALYZE_STATISTICS
--------------------
0
(1 row)
dbadmin=> --통계정보 생성 확인
dbadmin=> SELECT STATISTICS_TYPE , STATISTICS_UPDATED_TIMESTAMP , PROJECTION_NAME, PROJECTION_COLUMN_NAME
dbadmin-> FROM PROJECTION_COLUMNS
dbadmin-> WHERE TABLE_NAME = 'T'
dbadmin-> ORDER BY COLUMN_POSITION;
STATISTICS_TYPE | STATISTICS_UPDATED_TIMESTAMP | PROJECTION_NAME | PROJECTION_COLUMN_NAME
-----------------+-------------------------------+-----------------+------------------------
FULL | 2020-05-20 17:15:26.064861+09 | T_b1 | product_key
FULL | 2020-05-20 17:15:26.064861+09 | T_b0 | product_key
FULL | 2020-05-20 17:15:26.064861+09 | T_b1 | product_version
FULL | 2020-05-20 17:15:26.064861+09 | T_b0 | product_version
FULL | 2020-05-20 17:15:26.064861+09 | T_b0 | store_key
FULL | 2020-05-20 17:15:26.064861+09 | T_b1 | store_key
FULL | 2020-05-20 17:15:26.064861+09 | T_b0 | vendor_key
FULL | 2020-05-20 17:15:26.064861+09 | T_b1 | vendor_key
--중략
(38 rows)
dbadmin=> --실행계획 확인
dbadmin=> EXPLAIN SELECT COUNT(*) FROM T WHERE DATE_ORDERED = '2006-12-10';
QUERY PLAN
------------------------------
------------------------------
QUERY PLAN DESCRIPTION:
------------------------------
EXPLAIN SELECT COUNT(*) FROM T WHERE DATE_ORDERED = '2006-12-10';
Access Path:
+-GROUPBY NOTHING [Cost: 11K, Rows: 1] (PATH ID: 1)
| Aggregates: count(*)
| Execute on: All Nodes
| +---> STORAGE ACCESS for T [Cost: 11K, Rows: 2K] (PATH ID: 2)
| | Projection: public.T_b0
| | Filter: (T.date_ordered = '2006-12-10'::date)
| | Execute on: All Nodes
dbadmin=> --파티션 레벨의 통계 정보 수집
dbadmin=> SELECT ANALYZE_STATISTICS_PARTITION('PUBLIC.T', '2003-01-01', '2007-12-10');
ANALYZE_STATISTICS_PARTITION
------------------------------
0
(1 row)
dbadmin=> --실행계획 확인
dbadmin=> EXPLAIN SELECT COUNT(*) FROM T WHERE DATE_ORDERED = '2007-12-10';
QUERY PLAN
------------------------------
------------------------------
QUERY PLAN DESCRIPTION:
------------------------------
EXPLAIN SELECT COUNT(*) FROM T WHERE DATE_ORDERED = '2007-12-10';
Access Path:
+-GROUPBY NOTHING [Cost: 2, Rows: 1] (PATH ID: 1)
| Aggregates: count(*)
| Execute on: All Nodes
| +---> STORAGE ACCESS for T [Cost: 1, Rows: 2K(PARTITION-LEVEL STATISTICS)] (PATH ID: 2)
| | Projection: public.T_b1
| | Filter: (T.date_ordered = '2007-12-10'::date)
| | Execute on: All Nodes