확장성을 제공하기 위해 Kudu 테이블은 여러 태블릿 서버에 분산된 태블릿 단위로 나뉩니다. 각 행은 항상 특정 태블릿에 속하며, 이는 테이블 생성 시 설정된 파티셔닝 규칙에 따라 결정됩니다. Kudu는 다음 3가지 방식으로 데이터를 파티셔닝할 수 있습니다:
범위 파티셔닝 (Range Partitioning)
범위 파티셔닝은 데이터량에 따라 균형있게 기계 간에 분배하여 부하 불균형을 방지합니다.
아래와 같이 파티셔닝된 테이블을 생성하는 예제입니다:
create table rangeTable(CompanyId Type.INT32 , WorkId Type.INT32 , Name Type.STRING , Gender Type.STRING , Photo Type.STRING)
RANGE (CompanyId) (
PARTITION 0 <= VALUES < 10,
PARTITION 10 <= VALUES < 20,
PARTITION 20 <= VALUES < 30,
PARTITION 30 <= VALUES < 40,
PARTITION 40 <= VALUES < 50,
PARTITION 50 <= VALUES < 60,
PARTITION 60 <= VALUES < 70,
PARTITION 70 <= VALUES < 80,
PARTITION 80 <= VALUES < 90
)
코드 구현:
public class RangePartitionCreator {
private static ColumnSchema defineColumn(String name, Type type, boolean isPrimary) {
return new ColumnSchema.ColumnSchemaBuilder(name, type).key(isPrimary).build();
}
public static void main(String[] args) {
String masterAddresses = "hadoop01,hadoop02,hadoop03";
try (KuduClient client = new KuduClient.KuduClientBuilder(masterAddresses).defaultSocketReadTimeoutMs(6000).build()) {
List<ColumnSchema> columns = Arrays.asList(
defineColumn("CompanyId", Type.INT32, true),
defineColumn("WorkId", Type.INT32, false),
defineColumn("Name", Type.STRING, false),
defineColumn("Gender", Type.STRING, false),
defineColumn("Photo", Type.STRING, false)
);
Schema schema = new Schema(columns);
CreateTableOptions options = new CreateTableOptions().setNumReplicas(1);
List<String> partitionColumns = Collections.singletonList("CompanyId");
options.setRangePartitionColumns(partitionColumns);
for (int i = 0; i < 90; i += 10) {
PartialRow lowerBound = schema.newPartialRow();
lowerBound.addInt("CompanyId", i);
PartialRow upperBound = schema.newPartialRow();
upperBound.addInt("CompanyId", i + 10);
options.addRangePartition(lowerBound, upperBound);
}
client.createTable("rangeTable", schema, options);
} catch (Exception e) {
e.printStackTrace();
}
}
}
해시 파티셔닝 (Hash Partitioning)
해시 파티셔닝은 해시 값에 따라 데이터를 여러 버킷으로 분배합니다. 순서대로 데이터를 접근할 필요가 없는 경우 효과적입니다. 이를 통해 핫스팟 및 태블릿 크기의 불균형을 줄이는 데 도움이 됩니다.
테이블 생성 예제:
create table hashTable(CompanyId Type.INT32 , WorkId Type.INT32 , Name Type.STRING , Gender Type.STRING , Photo Type.STRING)
HASH (CompanyId) PARTITIONS 6,
RANGE (CompanyId) (
PARTITION UNBOUNDED
)
코드 구현:
public class HashPartitionCreator {
private static ColumnSchema defineColumn(String name, Type type, boolean isPrimary) {
return new ColumnSchema.ColumnSchemaBuilder(name, type).key(isPrimary).build();
}
public static void main(String[] args) {
String masterAddresses = "hadoop01,hadoop02,hadoop03";
try (KuduClient client = new KuduClient.KuduClientBuilder(masterAddresses).defaultSocketReadTimeoutMs(6000).build()) {
List<ColumnSchema> columns = Arrays.asList(
defineColumn("CompanyId", Type.INT32, true),
defineColumn("WorkId", Type.INT32, false),
defineColumn("Name", Type.STRING, false),
defineColumn("Gender", Type.STRING, false),
defineColumn("Photo", Type.STRING, false)
);
Schema schema = new Schema(columns);
CreateTableOptions options = new CreateTableOptions().setNumReplicas(1);
List<String> partitionColumns = Collections.singletonList("CompanyId");
options.addHashPartitions(partitionColumns, 6);
client.createTable("hashTable", schema, options);
} catch (Exception e) {
e.printStackTrace();
}
}
}
다단 파티셔닝 (Multilevel Partitioning)
Kudu는 단일 테이블에서 여러 단계의 파티셔닝을 조합할 수 있습니다. 적절히 사용하면 각 파티셔닝 유형의 장점을 보존하면서 단점들을 줄일 수 있습니다.
테이블 생성 예제:
create table multilevelTable(CompanyId Type.INT32 , WorkId Type.INT32 , Name Type.STRING , Gender Type.STRING , Photo Type.STRING)
HASH (CompanyId) PARTITIONS 10,
RANGE (CompanyId) (
PARTITION 0 <= VALUES < 10,
PARTITION 10 <= VALUES < 20,
PARTITION 20 <= VALUES < 30,
PARTITION 30 <= VALUES < 40,
PARTITION 40 <= VALUES < 50,
PARTITION 50 <= VALUES < 60,
PARTITION 60 <= VALUES < 70,
PARTITION 70 <= VALUES < 80,
PARTITION 80 <= VALUES < 90
)
코드 구현:
public class MultilevelPartitionCreator {
private static ColumnSchema defineColumn(String name, Type type, boolean isPrimary) {
return new ColumnSchema.ColumnSchemaBuilder(name, type).key(isPrimary).build();
}
public static void main(String[] args) {
String masterAddresses = "hadoop01,hadoop02,hadoop03";
try (KuduClient client = new KuduClient.KuduClientBuilder(masterAddresses).defaultSocketReadTimeoutMs(6000).build()) {
List<ColumnSchema> columns = Arrays.asList(
defineColumn("CompanyId", Type.INT32, true),
defineColumn("WorkId", Type.INT32, false),
defineColumn("Name", Type.STRING, false),
defineColumn("Gender", Type.STRING, false),
defineColumn("Photo", Type.STRING, false)
);
Schema schema = new Schema(columns);
CreateTableOptions options = new CreateTableOptions().setNumReplicas(1);
List<String> partitionColumns = Collections.singletonList("CompanyId");
options.addHashPartitions(partitionColumns, 10);
options.setRangePartitionColumns(partitionColumns);
for (int i = 0; i < 90; i += 10) {
PartialRow lowerBound = schema.newPartialRow();
lowerBound.addInt("CompanyId", i);
PartialRow upperBound = schema.newPartialRow();
upperBound.addInt("CompanyId", i + 10);
options.addRangePartition(lowerBound, upperBound);
}
client.createTable("multilevelTable", schema, options);
} catch (Exception e) {
e.printStackTrace();
}
}
}
해시 파티셔닝은 쓰기 처리량을 최대화하는 데 유리하며, 범위 파티셔닝은 태블릿의 무한 성장을 방지합니다. 이 두 가지를 결합하면 Kudu의 성능을 크게 향상시킬 수 있습니다.