개발/AWS
Athena
캐리캐리
2021. 12. 16. 13:00
Athena는 무엇이고 왜 사용할까요
AWS를 이용하게 되면 S3에 로그 파일도 저장하고 기타 여러 가지 정보를 저장합니다.
이렇게 저장된 정보를 Amazon Athena를 통해 조회를 할 수 있습니다.
Athena는 페이스북이 개발한 presto라는 엔진을 사용하는데 이유는 .. 아직 잘 모르겠는데
일반 RDB보다 속도가 대략 10배 정도 빠릅니다.
사용법은
presto가 다른 mysql ,oracle db와 같이 안시쿼리를 지원하므로 기존과 동일하게 사용할 수 있습니다.
다만 다른것이 아래와 같이 파티션으로 년, 월 , 일을 두어 특정 일자로 조회를 해야합니다.
(구성에 따라 다를 수 있습니다. )

또한 문법적으로 살짝 다른 부분들이 있습니다.
예를들면 mysql의 IFNULL = oracle의 decode = athena의 COALESCE이 있습니다.
구현부를 만들어보겠습니다.
저 같은 경우 mybatis와 연결을 하였으며 yml파일 내 관련 설정값을 불러와서 Config를 구성하였습니다.
또한 마이바티스 내 config파일에 등록한것 외에도 모델 , 앨리어스 애노테이션으로 등록된 것을 세션 팩토리에 추가하였습니다.
@Configuration
@EnableTransactionManagement
@MapperScan(
basePackages = {"패키지"},
annotationClass = AthenaDao.class, // AthenaDao 어노테이션이 붙은 DAO만 이 데이터소스를 사용한다.
sqlSessionFactoryRef = "athenaSqlSessionFactory",
sqlSessionTemplateRef = "athenaSqlSessionTemplate"
)
@RequiredArgsConstructor
public class AthenaConfig {
private final ApplicationContext applicationContext;
/*
*데이터 소스를 만들기 위해 커넥션풀 프로퍼티 객체를 반환하는 빈 선언
* prefix로 시작하는 값 주입
* */
@Bean(name = {"athenaDsConnectionProperties"})
@ConfigurationProperties(prefix = "spring.multi-datasource.athena-ds")
public PoolProperties getPoolProperties(){
return new PoolProperties();
}
/*
* athena 데이터소스를 반환하는 빈 선언
* */
@Bean(name = "athenaDatasource")
public DataSource getDatasource(@Autowired @Qualifier("athenaDsConnectionProperties") PoolProperties property) {
com.simba.athena.jdbc.DataSource ds = new com.simba.athena.jdbc.DataSource();
ds.setURL(property.getUrl());
return ds;
}
/*
* Mybatis 관련 SqlSessionFactory 반환 빈 선언
* */
@Bean(name = "athenaSqlSessionFactory")
public SqlSessionFactory athenaSqlSessionFactory(@Qualifier("athenaDatasource") final DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
sqlSessionFactory.setDataSource(dataSource);
//컨피그에 등록 된 패키지 모델 앨리어스 추가
sqlSessionFactory.setConfigLocation(applicationContext.getResource("classpath:mapper/mybatis-config.xml"));
sqlSessionFactory.setMapperLocations(applicationContext.getResources("classpath:mapper/**/*Mapper.xml"));
ClassLoader runClassLoader = Thread.currentThread().getContextClassLoader();
Reflections reflections = new Reflections(ClasspathHelper.forPackage("패키지"), new SubTypesScanner(false));
//Model의 이름을 가졌거나 Alias 애노테이션에 들어간 클래스를 추가
List<Class<?>> typeAliasRegistryList = new ArrayList<>();
reflections.getAllTypes().forEach(type -> {
Class<?> typeClass;
try {
typeClass = Class.forName(type, false, runClassLoader);
if (type.endsWith("Model") || typeClass.isAnnotationPresent(Alias.class)) {
typeAliasRegistryList.add(typeClass);
}
} catch (NoClassDefFoundError ignore) {
} catch (ClassNotFoundException ignore) {
}
});
Class<?>[] typeAliasRegistryArray = typeAliasRegistryList.toArray(new Class<?>[typeAliasRegistryList.size()]);
sqlSessionFactory.setTypeAliases(typeAliasRegistryArray);
return sqlSessionFactory.getObject();
}
@Bean(name = "athenaSqlSessionTemplate")
public SqlSessionTemplate athenaSqlSessionTemplate(@Qualifier("athenaSqlSessionFactory") SqlSessionFactory athenaSqlSessionFactory){
return new SqlSessionTemplate(athenaSqlSessionFactory);
}
/*
* 트랜잭션 발생 시 롤백
* */
@Bean(name = "athenaTransactionManager")
public DataSourceTransactionManager TransactionManager(@Autowired @Qualifier("athenaDatasource") DataSource DataSource) {
return new DataSourceTransactionManager(DataSource);
}
}
이러한 Config의 경우 AthenaDao 애노테이션이 호출하면 동작을 하며 Dao 내 해당 애노테이션을 추가하고 mappr.xml 내 Athena 관련 쿼리를 작성하면 정상 동작하는것이 확인이 됩니다.