반응형
개념
파티셔닝(Partitioning)이란?
- 하나의 데이터베이스 안에서 여러 파티션으로 나눠 데이터를 관리하여 성능 최적화와 관리 효율성을 높이는 방식을 말한다.
- 쿼리 성능 향상 및 데이터 관리 최적화를 위해 사용한다.
- 장점
- 쿼리 수행시 특정 파티션에만 접근하므로 쿼리 성능이 향상된다.
- 데이터 아카이빙 및 데이터 파기 등에 유용하다.
- 단일 데이터베이스를 관리하기 때문에 비교적 관리하기 쉽다.
- 단점
- 물리적으로 같은 데이터베이스 내에 존재하기 때문에 확장성은 제한적이다.
- 특정 쿼리가 여러 파티션에 걸쳐야할 경우 성능이 저하될 수 있다.
파티셔닝 종류
- RANGE 파티셔닝 : 연속적인 값 범위에 따라 데이터를 분리. ex) 날짜 범위별
- LIST 파티셔닝 : 특정 값 목록에 따라 데이터를 분리. ex) 지역별
- HASH 파티셔닝 : 해시 함수를 사용하여 데이터를 고르게 분산시켜 분리. 균등한 데이터 분포를 보장함
예제
MySQL 실행
docker-compose.yml
version: "3.3"
services:
mysql01:
image: mysql:9.0.1
ports:
- "13306:3306"
environment:
TZ: Asia/Seoul
MYSQL_DATABASE: test
MYSQL_ROOT_PASSWORD: 123456
command:
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
실행
docker-compose up -d
테이블 생성
CREATE TABLE Message
(
id CHAR(36),
sender VARCHAR(100),
receiver VARCHAR(100),
title VARCHAR(100),
contents VARCHAR(500),
createdAt DATETIME(3) NOT NULL,
PRIMARY KEY (id, createdAt) -- 파티션키는 기본키에 포함되어야함
)
PARTITION BY RANGE (TO_DAYS(createdAt)) (
PARTITION p_202408 VALUES LESS THAN (TO_DAYS('2024-09-01')),
PARTITION p_202409 VALUES LESS THAN (TO_DAYS('2024-10-01')),
PARTITION p_202410 VALUES LESS THAN (TO_DAYS('2024-11-01'))
);
application.yml
spring:
datasource:
hikari:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:13306/test
username: root
password: 123456
jpa:
open-in-view: false
properties:
hibernate:
hbm2ddl:
auto: none
show_sql: true
format_sql: false
use_sql_comments: false
implicit_naming_strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
physical_naming_strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
logging:
level:
org.hibernate.orm.jdbc.bind: trace
Message
@IdClass(Message.PrimaryKey::class)
@Entity
data class Message(
@Id
val id: String,
val sender: String,
val receiver: String,
var title: String,
var contents: String,
@Id
val createdAt: LocalDateTime,
) {
data class PrimaryKey(
val id: String = UUID.randomUUID().toString(),
val createdAt: LocalDateTime = LocalDateTime.now(),
) : Serializable
}
MessageRepository
@Repository
interface MessageRepository : JpaRepository<Message, Message.PrimaryKey> {
fun findByCreatedAtGreaterThanEqualAndCreatedAtLessThan(startAt: LocalDateTime, endAt: LocalDateTime): List<Message>
}
MessageTest
@SpringBootTest
class MessageTest {
@Autowired
private lateinit var messageRepository: MessageRepository
private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
@Test
fun test() {
messageRepository.save(Message(UUID.randomUUID().toString(), "tyler-1", "john-1", "title-1", "contents-1", LocalDateTime.parse("2024-08-05 00:00:00", formatter)))
messageRepository.save(Message(UUID.randomUUID().toString(), "tyler-2", "john-2", "title-2", "contents-2", LocalDateTime.parse("2024-08-06 00:00:00", formatter)))
messageRepository.save(Message(UUID.randomUUID().toString(), "tyler-3", "john-3", "title-3", "contents-3", LocalDateTime.parse("2024-08-30 00:00:00", formatter)))
messageRepository.save(Message(UUID.randomUUID().toString(), "tyler-4", "john-4", "title-4", "contents-4", LocalDateTime.parse("2024-09-05 00:00:00", formatter)))
messageRepository.save(Message(UUID.randomUUID().toString(), "tyler-5", "john-5", "title-5", "contents-5", LocalDateTime.parse("2024-10-05 00:00:00", formatter)))
// id, createdAt 복합키가 기본키이기 때문에 update 쿼리의 where 조건에도 id, createdAt가 모두 추가됨. createdAt 기반으로 특정 파티션을 찾아 쿼리 수행
val message = messageRepository.findByCreatedAtGreaterThanEqualAndCreatedAtLessThan(LocalDateTime.parse("2024-09-01 00:00:00", formatter), LocalDateTime.parse("2024-10-01 00:00:00", formatter))
messageRepository.save(message.first().copy(title = "title-22"))
val message1 = messageRepository.findByCreatedAtGreaterThanEqualAndCreatedAtLessThan(LocalDateTime.parse("2024-08-05 00:00:00", formatter), LocalDateTime.parse("2024-08-06 00:00:00", formatter)).first()
val message2 = messageRepository.findByCreatedAtGreaterThanEqualAndCreatedAtLessThan(LocalDateTime.parse("2024-09-01 00:00:00", formatter), LocalDateTime.parse("2024-10-01 00:00:00", formatter)).first()
assertEquals("title-1", message1.title)
assertEquals("title-22", message2.title)
}
}
반응형
'Development > Spring' 카테고리의 다른 글
[Spring] WebSocket (1) | 2024.12.09 |
---|---|
[Spring] HTTP Interface(RestClient, WebClient) (0) | 2024.11.24 |
[Spring] Circuit Breaker(with resilience4j) (0) | 2024.07.15 |
[Spring] Sharding (0) | 2024.07.12 |
[Spring] multi-module 프로젝트 구성하기(kotlin, gradle) (0) | 2024.07.07 |