Distribution 기본값 변경

Nick Lamb -

기본 Distribution

ClustrixDB는 해시 알고리즘(hashing algorithm)을 사용하여 테이블(relation) 또는 인덱스(representation)를 클러스터 내에 어떻게 배치해야 하는지 결정합니다. 해시할 컬럼을 해당 Representation에 대한 "분산 키(distribution key)"라고 하고 노드에서의 데이터의 위치를 결정합니다. 이를 위해 각 인덱스는 분산 키에 대한 메타데이터를 갖고 있습니다. 기본적으로 분산 키는 인덱스를 구성하는 컬럼의 수에 관계없이 인덱스의 첫 번째 컬럼(DISTRIBUTE = 1)을 사용합니다. 이것은 기본 키(primary key)를 포함한 모든 인덱스에 적용됩니다.

분산 키를 수정하는 방법을 비롯하여 이에 대한 자세한 내용은 DISTRIBUTE 설명서를 참조하십시오.

Distribution 늘리기

인덱스 또는 테이블에 대해 추가 컬럼을 포함하도록 분산 키를 수정하는 것이 종종 도움이 될 수 있습니다. 이 작업은 온라인 작업(Online DDL)이지만 Representation을 다시 작성해야 하므로 작업을 완료하는데 시간이 걸리고 큰 테이블과 인덱스의 경우 여유 공간이 필요합니다. 다른 alter 작업과 마찬가지로 이 작업은 피크 시간대를 피해서 실행하는 것이 좋습니다.

다음 섹션에서는 Distribution 변경시 고려할 상황에 대해 설명합니다.

컬럼 고유성(Uniqueness)

키의 첫 번째 컬럼에 고유한 값이 충분히 포함되어 있지 않으면 데이터베이스가 클러스터 전체에 Representation를 균등하게 분산하지 못합니다. 이는 분할 임계값(split threshold)을 초과하는 매우 큰 슬라이스가 되거나 최소 및 최대 슬라이스 사이즈 간에 큰 차이가 날 수 있습니다. 이로 인해 해당 슬라이스에 액세스하는 쿼리의 성능이 달라질 수 있습니다. 일반적인 지침은 인덱스의 첫 번째 키가 슬라이스의 Representation 수보다 적어도 더 많은 값을 포함해야 한다는 것입니다. 예를 들어, 600개의 슬라이스가 있는 테이블의 경우 키에 적어도 6000개의 고유한 값이 있어야 합니다.

다음 쿼리를 이용하여 시스템이 어떤 Representation이 distribution 변경을 통해 이점을 얻을 것으로 판단하는지 알 수 있습니다. 이 쿼리는 현재 distribution 및 키의 총 컬럼 개수를 알려줍니다. 열의 고유성(uniqueness)에 따라 distribution을 늘릴 수 있지만, 전체 열 개수와 같지 않게 변경해야 하는 것은 아닙니다. 참고: 적절한 distribution을 하기에 고유성(uniqueness)이 충분하지 않은 단일 컬럼 키(non-primary key)는 키본 키를 포함하여 재분산할 수 있습니다.

SELECT db.name           AS DATABASE, 
     rel.name          AS table,
     rep.name          AS index,
     rep.cont_keycount AS total_keycount,
     hd.range_keycount AS current_keycount,
     bytes,
     rhd.slice_size_deviance,
     node_write_deviance,
     vdev_write_deviance,
     node_read_deviance,
     vdev_read_deviance
FROM   system.rebalancer_hash_distributions rhd
     JOIN system.representations rep
       ON rep.representation = rhd.hash_dist
     JOIN system.relations rel
       ON rel.table = rep.relation
     JOIN system.DATABASES db
       ON db.db = rel.db
     JOIN system.range_hash_distributions hd
       ON hd.representation = rep.representation
WHERE  rhd.needs_redistribute
     AND rep.cont_keycount != hd.range_keycount;

분산할 열의 개수를 결정하려면 키의 각 컬럼의 고유성(uniqueness)를 조사해야 합니다. foo.bar 테이블에 속한 샘플 Representation (`col1`,`col2`)에 대해 테이블의 컬럼 수와 고유성(uniqueness)을 질의할 수 있습니다:


CREATE TABLE `bar` (
  `col1` bigint(20) unsigned not null,
  `col2` bigint(20) unsigned not null,
  PRIMARY KEY (`col1`,`col2`) /*$ DISTRIBUTE=1
) CHARACTER SET utf8 /*$ REPLICAS=2 SLICES=50 CONTAINER=layered */

explain select * from foo.bar;
+--------------------------------------------------------------+------------+-------------+
| Operation                                                    | Est. Cost  | Est. Rows   |
+--------------------------------------------------------------+------------+-------------+
| stream_combine                                               | 6690015.46 |   786516.00 |
|   index_scan 1 := bar.__idx_bar__PRIMARY                     |  103914.13 |   199750.30 |
+--------------------------------------------------------------+------------+-------------+
2 rows in set (0.10 sec)

select count(distinct (`col1`)),count(distinct(`col2`)) from foo.bar;
+-----------------------------+---------------------------+
| count(distinct (`col1`))    | count(distinct(`col2`))   |
+-----------------------------+---------------------------+
|                           5 |                      5200 |
+-----------------------------+---------------------------+
1 row in set (0.00 sec)


이 예제에서 col1은 매우 고유하지 않으므로 데이터는 5개의 버킷으로 해시 분산됩니다. 'ALTER TABLE foo.bar PRIMARY KEY DISTRIBUTE=2;'를 실행하여 두번째 컬럼이 분산 키에 추가되면 슬라이스 크기가 비슷해지고 클러스터 전체가 균형을 이루게 됩니다.

Parallelism 향상

키 분산을 변경하면 일부 플래너(planner) 연산자(operator)의 동작이 변경됩니다. 이렇게 하면 테이블에 대해 실행되는 쿼리가 더 많은 병렬 연산자를 사용할 수 있습니다. 아래 예제에서, 집계되는 데이터가 클러스터 전체에 분산되기 때문에 기본 키의 DISTRIBUTION을 변경하면 dist_stream_aggregate를 사용할 수 있습니다. 이것은 클러스터에 대한 작업이지만 이 쿼리(및 잠재적으로 해당 Representation을 질의하는 다른 쿼리)에 대한 쿼리 대기 시간이 짧아집니다. 또한, 분산 키가 길면 분산 컬럼이 GROUP BY 목록의 일부로 포함된 경우 GTM(Global Transaction Manager) 노드에서 더 많은 집계를 수행해야 하므로 비용이 많이 듭니다.

원본 Schema 및 Explain:


CREATE TABLE `bar` (
  `iDate` datetime not null,
  `c_code`   int(10) unsigned not null,
  `counter`  bigint(20) unsigned not null,
  `unique_count` bigint(20) unsigned not null,
  `area` varchar(32) not null,
  PRIMARY KEY (`iDate`,`c_code`,`area`) /*$ DISTRIBUTE=1 */
) CHARACTER SET utf8 /*$ REPLICAS=2 SLICES=400 CONTAINER=layered */;

sql> explain select sum(counter) from test.bar where iDate = '2017-06-22';
+---------------------------------------------------------------------------------+-------------+-------------+
| Operation                                                                       | Est. Cost   | Est. Rows   |
+---------------------------------------------------------------------------------+-------------+-------------+
| stream_aggregate expr0 := sum((1 . "counter"))                                  | 54050340.69 | 71114370.00 |
|   index_scan 1 := bar.__idx_bar__PRIMARY, iDate = param(0)                      | 39827461.69 | 71114370.00 |
+---------------------------------------------------------------------------------+-------------+-------------+
2 rows in set (2.80 sec)

Primary Key DISTRIBUTE=3:


CREATE TABLE `bar` (
  `iDate` datetime not null,
  `c_code`   int(10) unsigned not null,
  `counter`  bigint(20) unsigned not null,
  `unique_count` bigint(20) unsigned not null,
  `area` varchar(32) not null,
  PRIMARY KEY (`iDate`,`c_code`,`area`) /*$ DISTRIBUTE=3 */
) CHARACTER SET utf8 /*$ REPLICAS=2 SLICES=400 CONTAINER=layered */;

sql> explain select sum(counter) from test.bar where iDate = '2017-06-22';
+-------------------------------------------------------------------------------------+-------------+-----------+
| Operation                                                                           | Est. Cost   | Est. Rows |
+-------------------------------------------------------------------------------------+-------------+-----------+
| stream_aggregate expr0 := sum((0 . "expr0"))                                        | 25188878.89 |    800.00 |
|   stream_combine                                                                    | 25188713.89 |    800.00 |
|     dist_stream_aggregate expr0 := sum((1 . "counter"))                             |    31485.79 |      1.00 |
|       index_scan 1 := bar.__idx_bar__PRIMARY, iDate = param(0)                      |    30928.61 |  55217.97 |
+-------------------------------------------------------------------------------------+-------------+-----------+
4 rows in set (0.00 sec)

참고: 이 변경으로 인해 시스템에 브로드캐스트(broadcast)가 발생하게 되고 일부의 경우 전체적인 클러스터 성능에 영향을 미칠 수 있습니다. 브로드캐스트는 네트워크 간 트래픽 증가를 유발하고 불필요한 경우 성능상의 이점없이 경합을 가중시킵니다. 많이 사용되는 테이블의 distribution을 늘린 후에 성능이 저하되는 경우 다음 쿼리를 사용하여 브로드캐스트를 측정할 수 있습니다.


SELECT statement, 
       broadcasts, 
       exec_ms, 
       counts, 
       rows_read 
FROM   system.qpc_queries 
ORDER  BY broadcasts DESC 
LIMIT  5\G


이 쿼리를 실행하여 변경된 Representation에 갑자기 많은 수의 브로드캐스트가 있는 것으로 표시되면 해당 Representation의 distribution을 줄여야 할 수도 있습니다.

또 다른 질문이 있으십니까? 문의 등록

0 댓글

이 문서에는 댓글을 달 수 없습니다.
Zendesk 제공