mysql
EditSELECT LAST_INSERT_ID()
http://dev.mysql.com/downloads/gui-tools/5.0.html
날짜형식
DATE_FORMAT(now(),'%Y%m%d%H%i%s')
형식변환
http://blog.paran.com/sputnik/1022191
프랜드피드는 어떻게 MySQL을 사용해서 스키마 없는 데이터를 저장하나" 요약
Update
http://dev.mysql.com/doc/refman/5.0/en/update.html
[]
GUI tool
http://dev.mysql.com/downloads/gui-tools/5.0.html
날짜
DAYOFWEEK(date)
1 = Sunday, 2 = Monday, 7 = Saturday
select DAYOFWEEK('2007-01-05');
select DAYOFWEEK(now());
cast(ymd as date)
DATE_FORMAT(date_add(cast(gijun_ymd as date), interval 2-dayofweek(gijun_ymd) day), '%Y%m%d' )
Index
show index from tb_fund_chart_weekly
alter table 테이블명 add index 인덱스명 (칼럼명);
CREATE INDEX <인덱스명> ON <테이블명> ( 칼럼명1, 칼럼명2, … );
Cache
http://dev.mysql.com/doc/refman/5.1/en/ha-memcached-interfaces-mysqludf.htmlhttp://dev.mysql.com/doc/refman/5.1/en/ha-memcached-interfaces-mysqludf.html\[http://dev.mysql.com/doc/refman/5.1/en/ha-memcached-interfaces-mysqludf.html]
http://planet.mysql.com/entry/?id=26207
mysql jdbc
socketTimeout=60000&connectTimeout=60000
Innodb vs Myisam
http://dev.kthcorp.com/2011/06/17/why-we-need-to-use-innodb-on-mysql-vs-myisam-comparison/
Meta table
select * from mysql.userselect * from mysql.dbselect version()select * from mysql.general_logshow variables like 'log_output'
replication delay
http://www.mysqlperformanceblog.com/2011/07/29/reasons-for-mysql-replication-lag/
load data infile
options
http://dev.mysql.com/doc/refman/5.1/en/load-data.htmlhttp://dev.mysql.com/doc/refman/5.1/en/mysqlimport.html\[http://dev.mysql.com/doc/refman/5.1/en/mysqlimport.html]
performance
: 옵션 조정해서 비교하는 사례
http://www.mysqlperformanceblog.com/2008/07/03/how-to-load-large-files-safely-into-innodb-with-load-data-infile/ : perl script이용 chunk 사이즈 조정http://chrisjohnson.blogsite.org/php-and-mysql-data-import-performance/\[http://chrisjohnson.blogsite.org/php-and-mysql-data-import-performance/] : Php에서 load data in file의 성능비교 insert 성능 : http://dev.mysql.com/doc/refman/5.1/en/insert-speed.htmlhttp://kvz.io/blog/2009/03/31/improve-mysql-insert-performance/\[http://kvz.io/blog/2009/03/31/improve-mysql-insert-performance/] insert delayed : (myisam에서만 가능)
JDBC에 속성포함 예제
jdbc:mysql://127.0.0.1/test?logger=com.mysql.jdbc.log.Slf4JLogger&logSlowQueries=true&slowQueryThresholdMillis=1500&dumpQueriesOnException=true&explainSlowQueries=true&connectTimeout=1000&socketTimeout=2000
Column not found 에러 :
?useOldAliasMetadataBehavior=true
http://forums.mysql.com/read.php?39,424792,424792
http://forums.mysql.com/read.php?39,424792,430313#msg-430313
아래는 제공된 Markdown 문서를 Asciidoc 형식으로 변환한 내용입니다.
AsciiDoc
대용량데이터 처리를 위한 MySQL 최적화
"useServerPrepStmt=true" 옵션
- MySQL 서버에서 preparedStatement 를 파싱한 정보를 재활용하도록 유도하는 옵션
- MySQL Connector/J에서 useServerPrepStmt 옵션의 기본값은 false
- 별도의 설정을 하지 않으면 JDBC 드라이버가 PreparedStatement를 서버 측에서 준비(prepare)하지 않고, 클라이언트 측에서 SQL 문장을 완성하여 서버로 전송한다는 의미.
- PreparedStatement의 ? 파라미터를 실제 값으로 채운 완전한 SQL 쿼리 문자열을 매번 서버로 보내 실행하는 방식
- "클라이언트 측 PreparedStatement" 또는 "에뮬레이션된 PreparedStatement"
- 네트워크 호출이 1회만 발생
- MySQL버전 5.1미만에서는 이를 사용하면 MySQL의 쿼리 캐쉬를 쓰지 못하는 단점이 있었으나, 5.1이상에서는 둘다 사용할수 있음.
- useServerPrepStmts=true가 유리한 경우
- 동일한 쿼리가 매우 빈번하게 반복 실행되는 특정 작업: 예를 들어, 대량의 데이터를 반복적으로 삽입(INSERT)하는 배치(batch) 작업과 같이 한정된 종류의 쿼리가 수백, 수천 번 이상 실행되는 경우에는 서버 측 PreparedStatement의 이점이 큼.
- MariaDB 10.6 이상 사용 시: MariaDB 10.6부터는 useServerPrepStmts=true일 때 메타데이터 재전송을 피하는 최적화가 도입되어 성능 향상 폭이 더 커짐 ( https://jira.mariadb.org/browse/MDEV-19237 )
- 참고자료
- Real MySQL 750-753쪽
- useServerPrepStmts와 cachePrepStmts 옵션을 조합한 성능 테스트 결과
- https://vladmihalcea.com/mysql-jdbc-statement-caching/
- https://tech.kakaopay.com/post/how-preparedstatement-works-in-our-apps/
쓰기 성능 높이기 ( rewriteBatchedStatements=true 옵션)
- batchUpdate 쿼리를 합쳐서 성능을 높여줌 (multi-row insert)
- dump & restore에도 활용됨
- 전체 수행 성능에는 유리하나 insert문 하나하나의 수행 시간은 오래 걸리므로 리플리케이션 딜레이 발생에는 더 취약할 수 있음.
- "useServerPrepStmt=true" 옵션과 동시에 사용하면 에러가 발생할 수 있음.
- 최대한대로 최적화해야한다면 읽기 DataSource와 쓰기 DataSource를 분리할수도.
- 1건 레코드 크기* 운반 건수가
- 합친쿼리의 크기가 MySQL서버의 'max_allowed_packet' 설정값을 넘어가면
에러가 남.
- 'SHOW VARIABLES LIKE 'max%';' 로 확인 가능
- 'bulk_insert_buffer_size' 설정값에 따라서 성능이 달라질수 있음.
- connector-j의 8.0.29까지는 'useCursorFetch=true' 또는
useServerPrepStmts=true옵션과 함께 쓰면 rewriteBatchedStatements가 무시된다고 명시되어 있었으나 8.0.30에서는 문서에서 이 제한이 사라졌음. 실제 동작이 언제 바뀌었는지는 확실하지 않음.- `useCursorFetch=true`는 `useServerPrepStmts=true`를 강제함.
- https://dev.mysql.com/doc/relnotes/connector-j/en/news-8-0-30.html
- https://vladmihalcea.com/mysql-rewritebatchedstatements/
- connector-j의 8.0.28까지는 batchUpdate로 BLOB을 넣으려고 하는 NPE 발생
대용량 데이터 조회를 위한 옵션 파라미터
디폴트옵션들로는 MySQL에서는 JdbcCursorItemReader를 써도 OOM 날 수도 있음. 이를 위한 방법은 디폴트 옵션일때 사용되는 클라이언트사이드 커서는 모든 결과를 다 다운로드함. 이를 해결하기 위해 ResultSet Streaming, 서버 커서 사용할수 있음.
ResultSet Streaming
많은 건의 데이터를 한번에 받지 않고 Streaming으로 흘러보내면서 받는 방법 아래와 같이 Statement를 만들어야함.
PrepaedStatement statement = con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
statement.setFetchSize(Integer.MIN_VALUE);
'setFetchSize(Integer.MIN_VALUE)'은 JDBC규약과도 어긋남. java.sql.Statement의 javadoc에는 setFetchSize로 지정되는 값은 0보다 작으면 SQLException을 던진다고 적혀 있다.
- OOM이 방어되나 빈번한 통신이 일어나 성능이 느려질수 있음. (100만건이면 100만번 원격 통신)
- 한번에 몇건씩 fetch해 주는지까지는 제어가 안 됨.
- ResultSet이 닫히기 전까지 동일한 Connection에서 다른 쿼리를 실행할 수 없음.
- 참고자료
스프링 배치에서도 JdbcCursorItemReader.setFetchSize(Integer.MIN_VALUE)
로 지정하면 쿼리 결과를 한번에 다운로드 받지 않고 Streaming방식으로
가져감.
return new JdbcCursorItemReaderBuilder<T>()
.dataSource(this.dataSource)
.sql(sql)
.rowMapper(rowMapper)
.fetchSize(Integer.MIN_VALUE)
.verifyCursorPosition(false);
ResultSet.TYPE_FORWARD_ONLY 옵션은 JdbcCursorItemReader 에 이미 위의
Statement 생성시의 반영되어 있음.
verifyCursorPosition을 default값인 true로 둘 경우 아래와 같은 에러가 발생함
peration not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY.; nested exception is java.sql.SQLException: Operation not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY.
서버 커서
- MySQL 서버쪽에서 쿼리 결과를 담는 임시테이블을 만듬.
- JDBC URL에 "useCursorFetch=true" 옵션으로 가능해짐
- MySQL 5.0.2 이상에서 사용 가능
- 기본값이 false라 이 옵션이 없으면 클라이언트 커서만을 사용.
- useCursorFetch=true이면 useServerPrepStmt도 자동으로 true가 됨.
- 이 옵션을 쓰면 JdbcCursorItemReader.setFetchSize() 로는 실제 쓸 fetchSize (chunk 크기와 똑같은 값 권장)
- "defaultFetchSize" 옵션
- 서버 커서를 사용할때 디폴트로 한번에 몇건씩 읽어올지.
- 기본값이 0
- 참고 자료