Mysql EXPLAIN 을 사용 하여 SQL 문 구 를 분석 하고 최적화(계속)

21708 단어 EXPLAIN
오늘 은 여러 개의 SQL 문 구 를 최적화 시 켰 다.모두 EXPLAIN 의 공로 입 니 다.SQL 자구 의 집행 순서 와 집행 상황 을 분석 하고 명확 하 게 다음 과 같이 구체 적 인 분석 을 해 보 겠 습 니 다.
[다 표 공동 조회 최적화]
explain SELECT sql_no_cache pker.*,pk.*  FROM ng_game_pk AS pk ,ng_game_pker AS pker  where pker.pkid = pk.id and (pker.act_uid = 1 OR pker.def_uid = 1) AND pk.type <>4  GROUP BY pk.id limit 10;

+----+-------------+-------+--------+----------------------------------+---------+---------+--------------------+--------+----------------------------------------------+

| id | select_type | table | type   | possible_keys                    | key     | key_len | ref                | rows   | Extra                                        |

+----+-------------+-------+--------+----------------------------------+---------+---------+--------------------+--------+----------------------------------------------+

|  1 | SIMPLE      | pker  | ALL    | pkid,act_def                     | NULL    | NULL    | NULL               | 177543 | Using where; Using temporary; Using filesort |

|  1 | SIMPLE      | pk    | eq_ref | PRIMARY,type,idx_type_status_uid | PRIMARY | 4       | pwgbk8.7.pker.pkid |      1 | Using where                                  |

+----+-------------+-------+--------+----------------------------------+---------+---------+--------------------+--------+----------------------------------------------+

key:NULL,,,Extra:Using temporary,Using filesort 는 문장 이 느 립 니 다.type:모든 시계 스 캔,이보다 더 나 쁜 것 은 없습니다.
다음 변경 사항:
explain SELECT sql_no_cache pker.*,pk.*  FROM ng_game_pk AS pk ,ng_game_pker AS pker  where pker.pkid = pk.id and (pker.act_uid = 1 OR pker.def_uid = 1) AND pk.type <>4  GROUP BY pker.pkid limit 10;

+----+-------------+-------+--------+----------------------------------+---------+---------+--------------------+------+-------------+

| id | select_type | table | type   | possible_keys                    | key     | key_len | ref                | rows | Extra       |

+----+-------------+-------+--------+----------------------------------+---------+---------+--------------------+------+-------------+

|  1 | SIMPLE      | pker  | index  | pkid,act_def                     | pkid    | 4       | NULL               |   10 | Using where |

|  1 | SIMPLE      | pk    | eq_ref | PRIMARY,type,idx_type_status_uid | PRIMARY | 4       | pwgbk8.7.pker.pkid |    1 | Using where |

+----+-------------+-------+--------+----------------------------------+---------+---------+--------------------+------+-------------+

비교 하여 실행:
mysql> show profile for query 147;

+----------------------+----------+

| Status               | Duration |

+----------------------+----------+

| Creating tmp table   | 0.000372 |

| Copying to tmp table | 0.424248 |

| removing tmp table   | 0.002125 |

+----------------------+----------+

여 기 는 다른 집행 을 소홀히 했다.임시 시계 로 복사 하 는 것 을 보 는 데 대부분의 시간 이 걸 렸 다.설명 이 필요 합 니 다.Copying to tmp table 은 메모리 에 복사 되 어 있 습 니 다.Copying to tmp table on disk 라면 메모리 공간 이 부족 하 다 는 것 을 의미 합 니 다.MySQL 은 디스크 에 임시 표를 쓸 것 입 니 다.이 크기 의 설정 은 tmp 참조table_size。
현재 두 번 째 SQL 을 분석 하면,자구 id 가 같 습 니 다.그러면 실행 순 서 는 위 에서 아래로,현재 pker 표를 조회 하고 색인 은 pkid 입 니 다.그러면 GROUP BY pker.pkid 가 위의 자구 에 작용 하고 rows 가 10 이 라면 limit 10 도 여기에 작용 한다 고 볼 수 있 습 니 다.
[색인 최적화,복합 색인]
mysql> select count(*) from ng_game_pk WHERE status = 0 AND type = 4 AND uid = 1;

+----------+

| count(*) |

+----------+

|        0 |

+----------+

1 row in set (13.03 sec)
mysql> explain select count(*) from ng_game_pk WHERE status = 0 AND type = 4 AND uid = 1;
+----+-------------+------------+------+---------------+------+---------+-------+---------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref   | rows    | Extra       |
+----+-------------+------------+------+---------------+------+---------+-------+---------+-------------+
|  1 | SIMPLE      | ng_game_pk | ref  | type          | type | 1       | const | 1729551 | Using where |
+----+-------------+------------+------+---------------+------+---------+-------+---------+-------------

이 문 구 는 색인 type 을 사 용 했 지만 type 의 수치 범위 가 매우 좁다(1,2,3,4)사실 이 색인 은 그다지 쓸모 가 없다.다음은 우리 가 복합 색인 을 만들어 서 효과 가 어떤 지,
mysql> alter table ng_game_pk add index idx_type_status_uid(type,status,uid);

Query OK, 5831851 rows affected (1 min 43.20 sec)

Records: 5831851  Duplicates: 0  Warnings: 0

mysql> explain select count(*) from ng_game_pk WHERE status = 0 AND type = 4 AND uid = 1;

+----+-------------+------------+------+--------------------------+---------------------+---------+-------------------+------+-------------+

| id | select_type | table      | type | possible_keys            | key                 | key_len | ref               | rows | Extra       |

+----+-------------+------------+------+--------------------------+---------------------+---------+-------------------+------+-------------+

|  1 | SIMPLE      | ng_game_pk | ref  | type,idx_type_status_uid | idx_type_status_uid | 6       | const,const,const |    1 | Using index |

+----+-------------+------------+------+--------------------------+---------------------+---------+-------------------+------+-------------+

1 row in set (0.11 sec)

mysql> select count(*) from ng_game_pk WHERE status = 0 AND type = 4 AND uid = 1;

+----------+

| count(*) |

+----------+

|        0 |

+----------+

1 row in set (0.00 sec)

효과 가 좋 은 것 같 습 니 다.SQL 을 조금 수정 하면,
mysql> select sql_no_cache count(*) from ng_game_pk WHERE type = 4 and status>0 AND uid = 1;

+----------+

| count(*) |

+----------+

|     2649 |

+----------+

1 row in set (0.40 sec)

성능 이 또 떨 어 졌 습 니 다.이것 은 B-Tree 알고리즘 때 문 입 니 다.저장 엔진 은 첫 번 째 조건 범위 오른쪽 에 있 는 열 을 최적화 할 수 없습니다.그러면(type,status,,)뒤의 색인 이 효력 을 잃 습 니 다.
그럼 조정 해 봐..
mysql> drop index idx_type_status_uid on ng_game_pk;

mysql> alter table ng_game_pk add index idx_type_uid_status (type,uid,status);

결국 성능 이 또 향상 되 었 다.
---------------------------EOF--------------------------------
참고:
#'고성능 MySql(제2판)'
#고성능 웹 사이트 구축
http://www.cnitblog.com/aliyiyi08/archive/2008/09/09/48878.html
# http://www.perfgeeks.com/?p=460

좋은 웹페이지 즐겨찾기