mysql-성능튜닝 #2

DB 2008. 5. 23. 07:02


1. mysql은 동적으로 변화 가능한 옵션은 3가지로 나눌 수 있다.
- session : 조정된 값은 오직 현재 커넥션에만 영향을 미친다.
- global : 조정된 값이 전체 서버에 영향을 미친다.
- both : 값을 변화시킬 때 session/global을 반드시 명기해야 한다.


mysql> show global variables like 'query%';
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| query_alloc_block_size       | 8192    |
| query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 4096    |
| query_cache_size             | 0       |
| query_cache_type             | ON      |
| query_cache_wlock_invalidate | OFF     |
| query_prealloc_size          | 8192    |
+------------------------------+---------+
7 rows in set (0.00 sec)

mysql> show session variables like 'query%';
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| query_alloc_block_size       | 8192    |
| query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 4096    |
| query_cache_size             | 0       |
| query_cache_type             | ON      |
| query_cache_wlock_invalidate | OFF     |
| query_prealloc_size          | 8192    |
+------------------------------+---------+
7 rows in set (0.00 sec)


2.  변경된 옵션 적용하기
set global(또는 session) parameter =value
- 동작 중에 변경된 옵션은 서버 재 시작 전까지미만 적용된다.
- 영구히 변경하려면, /etc/my.cnf 파일을 수정해야 한다.
- super 권한이 있어야 바꿀 수 있다.

3. 주요 옵션 (show varialbles like '...%' 이용)
(1) table_cache (디폴트 64): 사용하는 테이블에 대한 핸들러를 캐시에 저장, opend_tables 항목이 높을 경우 table_cache를 높인다.
(2) thread_cache_size(디폴트 0) : 재 사용을 위해 보관할 쓰래드 수, thread_created가 높을 경우 증가된다. 클라이언트가 커넥션 풀을 쓰는 경우는 의미가 없다.
(3) max_connections(기본 100) : 허용 가능한 최대 동시 접속수, 쓰레드 관련 메모리 튜닝시 매우 중요, 각각의 커넥션은 최소 thread_stack의 사이즈만큼의 메모리 사용
(4) connect_timeout  : connect요청받고 몇초간 기다릴지
(5) net_buffer_length : 클라이언트에 보내는 초기 메시지의 바이트 수 조절한다.
(6) max_allowd_packet : 서버 / 클라이언트간 최대 전송 가능 패킷 크기를 설정한다., Text나 bloc컬럼이 많이 있거나, 리플리케이션을 하는 경우 최소 16M이상 잡아야 한다.
(7) back_log (디폴트 50) : connection이 대량으로 몰릴 때 큐에 대기가능한 커넥션의 갯수
(8) wait_timeout : 커넥션의 타임아웃
(9) net_retry_count : 통신이 잘못되어 실패할 때, 몇 번까지 재시도할지
(10) max_connect_error : 계속적으로 문제를 발생시키는 클라이언트를 몇번째 재시도후 block할지 지정. 한번 block되면, 서버를 재시작하거나 flush host명령을 실행하기 전까지 접속 불가 일반적인 경우.. 내부에서만 쓸 경우가 많아서 크게 잡아놓음
   나의 경우는 다음과 같이 지정
max_connections를 1000, 이때  thread_stack은 196608, thread_cache_size는 4.
connect_timeout : 5,  max_allowed_packet : 33,553,408(리플리케이션 적용) , back_log는 50
max_user_connections : 0 ,  max_connect_errors  99999999


3. 주요 환경변수 (show staus like 'thread..%' 이용)
(1) Connection관련
- Max_used_connections (720) : 피크 타임의 동시 접속 수, 튜닝의 제일 중요한 요소임
- Bytes_received (3656293909) / Bytes_sent (1293843766) : 모든 클라이언트와 전송된 바이트의 총합
- connections( 2045524 ) : 시도된 connection의 합
- Aborted_connects (40979) : 어플리케이션 또는 mysql의 커넥션 관련 옵션이 잘 못 될 수 있다.
(2) Thread 관련
-thread_created:서버 시작후, 현재까지 만들어진 총 쓰레드의 갯수
-thread_connected: 현재 열려있는 쓰레드수
-thread_cached : 재사용 가능한 동작 중이지 않은 쓰레드
-thread_running : sleeping 상태가 아닌 쓰레드 수
 [master]
| Threads_cached    | 43    |
| Threads_connected | 23    |
| Threads_created   | 66    |
| Threads_running   | 3     |
 [slave]
| Threads_cached    | 120   |
| Threads_connected | 383   |
| Threads_created   | 1681  |
| Threads_running   | 1     |
- slow_launch_threads :쓰래드 생성에 걸린 시간이 slow_launch_time 이상 걸린 쓰래드의 수. Slow_launch_time은 기본 2초이다. 0에 가까와야 좋은 것이다. 내 db는 0이군.
 *쓰레드 캐쉬의 적중률은  threads_created/connections로 계산 가능
A DB(캐슁용) : 1681/1505789 : 0.1%의 쓰레드 캐쉬의 적중률을 보여준다 (현재 thread_cache_size : 4)
B DB(어드민용) : 179348 / 2046107  : 8.7%의 쓰레드 캐쉬의 적중률을 보여준다 (현재 thread_cache_size : 128 )
=>thread_cache_size나 높여볼까나? 확실히 thread_cache_size가 높은 것이 훨씬 높다.
(3) Handler
일반적인 해석
  - handler_read_first가 높은 경우  많은 풀 인덱스 스캔이 이루어짐
  - handler_read_next가 높은 경우  풀 인덱스 스캔과 레인지 스캔이 이루어짐
  - handler_read_rnd가 높은 경우  많은 풀 테이블 스캔과 레인지 스캔이 이루어짐
  - handler_read_key가 높은 경우  인덱스를 읽는 경우가 많음
 [A DB(캐슁용)] => 별 튜닝 요소가 없다.
| Handler_commit             | 0     |
| Handler_delete             | 0     |
| Handler_discover           | 0     |
| Handler_prepare            | 0     |
| Handler_read_first         | 0     |
| Handler_read_key           | 0     |
| Handler_read_next          | 0     |
| Handler_read_prev          | 0     |
| Handler_read_rnd           | 0     |
| Handler_read_rnd_next      | 19    |
| Handler_rollback           | 0     |
| Handler_savepoint          | 0     |
| Handler_savepoint_rollback | 0     |
| Handler_update             | 0     |
| Handler_write              | 25    |
 [B DB(어드민용)] =>튜닝 요소가 많다.  많은 풀 테이블 스캔과 레인지 스캔이 이루어지는 것 같다.
| Handler_commit        | 199415     |
| Handler_delete        | 269322     |
| Handler_discover      | 0          |
| Handler_read_first    | 67565      |
| Handler_read_key      | 13910141   |
| Handler_read_next     | 429593667  |
| Handler_read_prev     | 2196569    |
| Handler_read_rnd      | 372568     |
| Handler_read_rnd_next | 2211096685 |
| Handler_rollback      | 1415609    |
| Handler_update        | 595584     |
| Handler_write         | 2026479    |

 

4. 성능
(1) MySQL의 느린 응답을 나타낸다. => slow_queries와 slow_launch_threads
(2) 부하가 심하다는 것을 나타낸다 =>   threads_created,  max_used_connections,  opend_tables이 큰 경우 (이 경우 table_cache를 올리자)
(3) 인덱스를 많이 읽는다. => handler_read_key가 높은 경우 
(4) 락 경쟁과 관련된 항목 =>  table_locks_waited VS table_locks_immediate , 만약 table_locks_waited가 높으면, myisam에서 innodb로 변경하는 것이 좋다.
A DB(캐슁)
| Table_locks_immediate | 20498565 |
| Table_locks_waited    | 0        |
B DB(어드민)
| Table_locks_immediate | 9500191 |
| Table_locks_waited    | 12509   |
(5) 메모리에 적용할 수 없는 큰 임시 테이블이 많이 만들어졌다 => created_tmp_disk_tables
=>  tmp_table_size를 올려서 과도한 DISK I/O가 발생하는 것을 막는다. 즉, 디스크를 안쓰고, 메모리를 쓰도록 한다.
A DB(캐슁) |Created_tmp_disk_tables | 0   (tmp_table_size | 67108864 )
B DB(어드민)| Created_tmp_disk_tables | 107  ( tmp_table_size | 33554432 )
(6)  select쿼리가 최적화 되지 못했다 => Select_xxx
=> select_full_join과 select_range_check는 많거나 다른 인덱스가 필요하다.
(6) sort_xxx 환경변수들의 값이 크다 => 쿼리에 따라 ordering 및 grouping 비용 크다.
=> sort_buffer_size가 크게 설정한다. 25%이상의 성능 향상을 기대할 수 있다. sort_buffer에 데이터를 정렬 한 후 실제 결과값을 처리하는 것은 read_rnd_buffer_size에 영향을 준다.
  

5. 최적화
(1) Table Cache 최적화
- table_cache 값을 올릴 때, mysqld가 필요로 하는 file descriptor의 수가 증가한다.
- MyISAM 엔진을 사용하는 경우 열려있는 각각의 테이블에 대해 하나의 file descriptor가 필요하게 되고, 게다가 인덱스 파일을 위해 하나의 file descriptor가 더 필요하다.
- 대부분의 운영체제에서는 프로세스당 사용할 수 있는 file descriptor의 수가 제한되는데, 이를 위해서 ulimit을 이용해서 file descript를 최대한 unlimited로 수정하는 것이 좋다.
- Opend_table 환경변수가 높을 때, 그리고 FLUSH TABLE을 자주 수행하지 않는다면 table_cache를 높이는 것이 좋다.
(2) Table Scan 최적화
- 디스크 억세스를 줄이기 위해 read_buffer가 사용된다.
- read_buffer_size는 기본 128Kb의 크기를 가지고, 높을 수록 테이블 스캔의 성능을 높여준다.
- 높여주되 지나치게 큰 값을 잡는 것은 좋지 않다. 기본적으로 테이블 스캔을 수행하는 모든 쓰래드에 할당될 수 있다.
(3) Join
- 조인되는 컬럼에 인덱스가 존재하지 않을 경우 성능이 매우 떨어진다.
- 인덱스를 추가할 수 없는 경우 join_buffer_size를 높인다.
- 두 테이블 간에 풀 조인이 일어날 경우 하나의 join_buffer가 할당되고 인덱스가 적용되지 않는 조인의 테이블 수가 늘어나는 만큼의 join_buffer가 할당된다.
(4) querty cache
select 쿼리와 그 결과를 저장한다. Query_cache_size를 클 수록 쿼리 캐시 싸이즈도 커진다. 하지만, 테이블이 바뀌면, Query cache는 모두 reset된다.
query_cache_limit을 조정함으로써 쿼리 캐시에 저장될 최대 쿼리 크기를 조절할 수 있고, Query_cache_min_res_unit(block size)를 설정하여 쿼리 캐시의 조각화를 줄일 수도 있다. 기본값은 4K이다.
Qcache_hits 와 Com_select를 비교하여 쿼리 캐시 적중률을 계산하여 성능을 최적화 할 수 있다.

'DB' 카테고리의 다른 글

mysql-성능튜닝#3(mysisam튜닝)  (0) 2008.05.23
mysql-성능튜닝 #4(innodb)  (0) 2008.05.23
mysql-성능튜닝 #2  (0) 2008.05.23
mysql- 성능 튜닝 #1  (0) 2008.05.23
mysql 의 wait_timeout의 의미  (0) 2008.05.23
mysql> show variables  (0) 2008.05.23
Posted by 김용환 '김용환'

댓글을 달아 주세요