[phpfest 2013] real mysql
DESCRIPTION
PHPFest 2013TRANSCRIPT
Real MySQL
Real MySQL http://cafe.naver.com/realmysql
Internal temporary table
•FROM 절의 서브 쿼리 -> 임시 테이블(Derived) SELECT * FROM ( SELECT * FROM ( SELECT * FROM tab WHERE fd IN (1) ) x ) y; +----+-------------+------------+ | id | select_type | table | +----+-------------+------------+ | 1 | PRIMARY | <derived2> | | 2 | DERIVED | <derived3> | | 3 | DERIVED | tab | +----+-------------+------------+
Real MySQL http://cafe.naver.com/realmysql
Internal temporary table
•사용된 임시 테이블 개수 mysql> SHOW STATUS LIKE 'Created_tmp_tables‘; +-------------------------+-------+ | Created_tmp_tables | 13 | +-------------------------+-------+ mysql> SELECT * FROM ( SELECT * FROM ( SELECT * FROM tab where fd in (1)) x) y; … mysql> SHOW STATUS LIKE 'Created_tmp_tables‘; +-------------------------+-------+ | Created_tmp_tables | 15 | +-------------------------+-------+
Real MySQL http://cafe.naver.com/realmysql
Deterministic
•CREATE FUNCTION CREATE FUNCTION getCurrentTime() RETURN DATETIME [ DETERMINISTIC | NOT DETERMINISTIC ] BEGIN DECLARE v_now DATETIME; SELECT NOW() INTO v_now; RETURN v_now; END
Real MySQL http://cafe.naver.com/realmysql
Deterministic
•두 쿼리의 차이는 ? SELECT * FROM huge_table WHERE expire_dttm > getCurrTime_DETERM (); SELECT * FROM huge_table WHERE expire_dttm > getCurrTime_NOTDETERMIN ();
• SYSDATE()와 NOW() 함수의 차이는 ?
Real MySQL http://cafe.naver.com/realmysql
Deterministic
•NOT-DETERMINISTIC Function +----+-------------+----------+------+ | id | select_type | table | type | +----+-------------+----------+------+ | 1 | SIMPLE | huge_tab | ALL | +----+-------------+----------+------+
• SYSDATE()와 NOW() 함수의 차이는 ?
Real MySQL http://cafe.naver.com/realmysql
IN (subquery)
•[NOT] IN (subquery)는 비효율적 •절대 subquery가 먼저 처리되지 못함
SELECT * FROM tab outer WHERE fd IN (SELECT fd FROM tab inner); +----+--------------------+-------+ | id | select_type | table | +----+--------------------+-------+ | 1 | PRIMARY | outer | | 2 | DEPENDENT SUBQUERY | inner | +----+--------------------+-------+
Real MySQL http://cafe.naver.com/realmysql
IN (subquery)
•실행 계획의 의미 +----+--------------------+-------+ | id | select_type | table | +----+--------------------+-------+ | 1 | PRIMARY | outer | | 2 | DEPENDENT SUBQUERY | inner | +----+--------------------+-------+ FOR (row1 IN outer){ exist( SELECT * FROM inner WHERE inner.fd=row1.fd ) }
Real MySQL http://cafe.naver.com/realmysql
IN (subquery)
•IN (subquery) Join이나 Derived 테이블 SELECT * FROM tab outer, tab inner WHERE outer.fd=inner.fd;
•NOT IN (subquery)
Anti-Join이나 Dervied를 이용한 Anti-Join SELECT * FROM tab outer LEFT JOIN tab1 inner WHERE inner.fd=outer.fd WHERE inner.fd IS NULL;
Real MySQL http://cafe.naver.com/realmysql
IN (subquery)
•서브 쿼리에서 중복 제거 필요시 Derived 테이블 이용 SELECT [STRAIGHT_JOIN] * FROM (SELECT fd FROM tab inner GROUP BY …) x, tab outer WHERE outer.fd = x.fd
•서브 쿼리 내용 상수화 SELECT * FROM tab outer WHERE outer.fd IN ( 1,2,3 )
Real MySQL http://cafe.naver.com/realmysql
Transaction propagation
• A 데이터베이스의 트랜잭션에 외부 작업 개입
• 마스터와 슬레이브 DB 작업 혼재 BEGIN UPDATE master_tbl SET … WHERE … SELECT * FROM slave_tbl WHERE … UPDATE master_tbl SET … WHERE … Commit / Rollback
Real MySQL http://cafe.naver.com/realmysql
Transaction propagation
• DB 트랜잭션 중간에 외부 네트워크 작업 BEGIN UPDATE tbl SET … WHERE … Cassandra or HBase SET … Send email or some other network job … Commit / Rollback
Real MySQL http://cafe.naver.com/realmysql
Transaction propagation
• 외부 작업 지연시 MySQL 서버의 레코드 잠금 시간 연장
• MySQL 서버의 Record 잠금 해제 지연 및 다른 세션의 잠금 대기 길어짐
• MySQL 서버는 큰 부하 없이, 아무런 작업도 처리 못함
• UndoRecord와 SystemTablespace ⇧ 많은 Undo로 인한 SELECT 성능 ⇩
Real MySQL http://cafe.naver.com/realmysql
Transaction propagation
• 트랜잭션 모니터링 mysql> SHOW ENGINE INNODB STATUS; ------------ TRANSACTIONS ------------ … ---TRANSACTION 3F0B, ACTIVE 23 sec, OS thread id 1252 1 lock struct(s), heap size 320, 0 row lock(s), undo log entries 1 MySQL thread id 1, query id 85 localhost 127.0.0.1 root ...
• Unix 계열 OS mysql> pager grep ACTIVE
Real MySQL http://cafe.naver.com/realmysql
한방 쿼리
SELECT
IFNULL(COUNT(fd1),0) as fd1, IFNULL(AVG(fd5),0) as fd4, IFNULL(fd6, 'Y') as fd5,
FROM ( SELECT fd1, fd2, 1 as fd3,
IF(fd4 <> fd6, 0,1) as fd4, IF(fd5 <> fd6, 1,0) as fd5, 0 as fd6 , 0 as fd7, fd8
FROM tab1 a
INNER JOIN tab2 b ON a.fd10 = b.fd10
WHERE b.fd13 IN (1, 2, 3, 4)
AND b.fd14 >= DATE_ADD('2011-10-08', INTERVAL 12 HOUR)
AND b.fd15 < DATE_ADD('2011-10-09', INTERVAL 12 HOUR)
GROUP BY fd1, fd2, fd3
UNION ALL
SELECT 0,0,0,0,0,1,0,a.fd1
FROM tab4 a
LEFT JOIN tab6 b ON a.fd1 = b.fd1
and b.fd11 < DATE_ADD('2013-10-08', INTERVAL 12 HOUR)
and b.fd12 in (12, 13)
WHERE a.fd13 IS NOT NULL
and a.fd15 IN (111,109)
…
…
…
Real MySQL http://cafe.naver.com/realmysql
한방 쿼리
• 충분한 튜닝 능력과 집중력 필수
– 쿼리를 튜닝해줄 DBA가 있다면 OK
– 만약 튜닝 능력⇩ + DBA가 없다면 내게 익숙한 절차적 개발 언어 적극 활용
• 단순해질수록 고도의 튜닝 능력 불필요
• 잘게 샤딩된 MySQL -> 복잡한 쿼리 X
• 쿼리가 어떻게 작동할지 잘 모르겠다면, 컨트롤이 가능한 수준까지 쪼개에서 실행
Real MySQL http://cafe.naver.com/realmysql
INDEX
• UNIQUE INDEX ?
• PRIMARY KEY 또는 UNIQUE INDEX로 Clustering
• Secondary Index는 PK 포함 (InnoDB)
• 인덱스 많을수록 INSERT UPDATE DELETE ⇩ SELECT 성능 ⇧
Real MySQL http://cafe.naver.com/realmysql
INDEX
• 인덱스 중복과 중첩 INDEX (fd1, pk1) = INDEX (fd1) UNIQUE INDEX (fd1) ⊃ INDEX (fd1) INDEX (fd1, fd2) ≠ INDEX (fd2, fd1) INDEX (pk1, fd1) ≠ INDEX (fd1, pk1) INDEX (fd1, fd2) ⊂ INDEX (fd1, fd2, fd3)
Real MySQL http://cafe.naver.com/realmysql
Real MySQL QnA (http://cafe.naver.com/realmysql)