728x90
반응형
목차는 DB 목차 에 있습니다.
[DB 13편] MySQL 옵티마이저 힌트 정리
아래 예시에 사용된 DDL, DML
옵티마이저 힌트
- 옵티마이저를 컨트롤 할 수 있는 방법 중의 하나이며, 개별 구문내에서 사용 가능합니다.
- /*+ … */ 로 사용가능합니다.
- ex) select /*+ … HINT */
- 사용할 때, 주의사항으로는 테이블에 alias 가 있을 경우 alias 명을 써줘야 합니다.
JOIN_FIXED_ORDER
- 조인순서를 강제합니다.
- 사용법은 select /*+ JOIN_FIXED_ORDER () */ 이며, 쿼리에 입력된 순으로 조인순서를 강제합니다.
HINT 적용 전 쿼리 및 실행계획
- 조인 순서가 team, team_member, member_addr 순으로 조인된 것을 알 수 있습니다.
# 사용 쿼리
explain format = json
select * from team t, team_member tm, member_addr ma
where t.team_id = tm.team_id
and tm.team_member_id = ma.member_id
and tm.team_id = 1
;
# 실행계획
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "1.95"
},
"nested_loop": [
{
"table": {
"table_name": "t",
"access_type": "const",
"possible_keys": [
"PRIMARY"
],
"key": "PRIMARY",
"used_key_parts": [
"team_id"
],
"key_length": "8",
"ref": [
"const"
],
"rows_examined_per_scan": 1,
"rows_produced_per_join": 1,
"filtered": "100.00",
"cost_info": {
"read_cost": "0.00",
"eval_cost": "0.10",
"prefix_cost": "0.00",
"data_read_per_join": "784"
},
"used_columns": [
"team_id",
"team_name"
]
}
},
{
"table": {
"table_name": "tm",
"access_type": "ref",
"possible_keys": [
"PRIMARY",
"FK9ubp79ei4tv4crd0r9n7u5i6e"
],
"key": "FK9ubp79ei4tv4crd0r9n7u5i6e",
"used_key_parts": [
"team_id"
],
"key_length": "8",
"ref": [
"const"
],
"rows_examined_per_scan": 2,
"rows_produced_per_join": 2,
"filtered": "100.00",
"cost_info": {
"read_cost": "0.50",
"eval_cost": "0.20",
"prefix_cost": "0.70",
"data_read_per_join": "1K"
},
"used_columns": [
"team_member_id",
"name",
"team_id"
]
}
},
{
"table": {
"table_name": "ma",
"access_type": "ALL",
"rows_examined_per_scan": 5,
"rows_produced_per_join": 2,
"filtered": "20.00",
"using_join_buffer": "hash join",
"cost_info": {
"read_cost": "0.25",
"eval_cost": "0.20",
"prefix_cost": "1.95",
"data_read_per_join": "624"
},
"used_columns": [
"addr_id",
"zip_code",
"addr_detail",
"member_id"
],
"attached_condition": "(`training`.`ma`.`member_id` = `training`.`tm`.`team_member_id`)"
}
}
]
}
}
HINT 적용 후 쿼리 및 실행계획
- 힌트를 적용 후, 조인순서가 team_member, member_addr, team 순으로 변경된 것을 확인할 수 있습니다.
# 쿼리
explain format = json
select /*+ JOIN_FIXED_ORDER () */
*
from team_member tm, member_addr ma , team t
where t.team_id = tm.team_id
and tm.team_member_id = ma.member_id
and tm.team_id = 1
;
# 실행계획
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "2.40"
},
"nested_loop": [
{
"table": {
"table_name": "tm",
"access_type": "ref",
"possible_keys": [
"PRIMARY",
"FK9ubp79ei4tv4crd0r9n7u5i6e"
],
"key": "FK9ubp79ei4tv4crd0r9n7u5i6e",
"used_key_parts": [
"team_id"
],
"key_length": "8",
"ref": [
"const"
],
"rows_examined_per_scan": 2,
"rows_produced_per_join": 2,
"filtered": "100.00",
"cost_info": {
"read_cost": "0.50",
"eval_cost": "0.20",
"prefix_cost": "0.70",
"data_read_per_join": "1K"
},
"used_columns": [
"team_member_id",
"name",
"team_id"
]
}
},
{
"table": {
"table_name": "ma",
"access_type": "ALL",
"rows_examined_per_scan": 5,
"rows_produced_per_join": 2,
"filtered": "20.00",
"using_join_buffer": "hash join",
"cost_info": {
"read_cost": "0.25",
"eval_cost": "0.20",
"prefix_cost": "1.95",
"data_read_per_join": "624"
},
"used_columns": [
"addr_id",
"zip_code",
"addr_detail",
"member_id"
],
"attached_condition": "(`training`.`ma`.`member_id` = `training`.`tm`.`team_member_id`)"
}
},
{
"table": {
"table_name": "t",
"access_type": "const",
"possible_keys": [
"PRIMARY"
],
"key": "PRIMARY",
"used_key_parts": [
"team_id"
],
"key_length": "8",
"ref": [
"const"
],
"rows_examined_per_scan": 1,
"rows_produced_per_join": 2,
"filtered": "100.00",
"cost_info": {
"read_cost": "0.25",
"eval_cost": "0.20",
"prefix_cost": "2.40",
"data_read_per_join": "1K"
},
"used_columns": [
"team_id",
"team_name"
]
}
}
]
}
}
JOIN_PREFIX
- 처음 조인순서를 명시합니다.
사용 예시
- team_member, member_addr 을 먼저 조인하라고 hist 를 준 예시입니다.
# 쿼리
explain format = json
select /*+ JOIN_PREFIX (tm, ma) */
*
from team_member tm, member_addr ma , team t
where t.team_id = tm.team_id
and tm.team_member_id = ma.member_id
and tm.team_id = 1
;
JOIN_ORDER
- JOIN_FIXED_ORDER 와는 다르게 옵티마이저에게 join 순서를 권유하는 명령어입니다. 옵티마이저가 판단했을 때, 효율이 안좋다면 사용되지 않습니다.
사용 예시
- 조인 순서를 team_member, member_addr, team 순으로 힌트를 준 것 입니다.
# 쿼리
explain format = json
select /*+ JOIN_ORDER (tm, ma, t) */
*
from team_member tm, member_addr ma , team t
where t.team_id = tm.team_id
and tm.team_member_id = ma.member_id
and tm.team_id = 1
;
Hash Join, No Hash Join
- Hash Join 을 사용할지 안할지를 명시하는 힌트 입니다.
사용 예시
select /*+ NO_HASH_JOIN (t,tm) */ * from team t, team_member tm
where t.team_id = tm.team_id
;
Reference
'database' 카테고리의 다른 글
[DB 15편] 정규화, 비정규화 (0) | 2023.01.10 |
---|---|
[DB 14편] MySQL Index Hints 정리 (3) | 2022.11.29 |
[DB 12편] MySQL 실행계획 2탄 (실행계획 상세) (0) | 2022.11.28 |
[DB 11편] MySQL 실행계획 1탄 (실행계획 순서) (0) | 2022.11.28 |
[DB 10편] MySQL 확장성 (스케일링, 샤딩) (0) | 2022.11.25 |
댓글