MySQL 의 두 가지 임시 테이블
외부 임시 테이블
CREATE TEMPORARY TABLE 을 통 해 만 든 임시 표를 외부 임시 표 라 고 합 니 다.이 임시 시 계 는 현재 사용자 에 게 만 보 입 니 다. 현재 세 션 이 끝 날 때 이 임시 시 계 는 자동 으로 종 료 됩 니 다.이 임시 표 의 이름 은 임시 표 와 같 을 수 있 습 니 다. (같은 이름 이 아 닌 임시 표 는 임시 표 가 삭 제 될 때 까지 현재 세 션 을 볼 수 없습니다.)
내부 임시 테이블
내부 임시 표 는 특수 경량급 의 임시 표 로 성능 최적화 에 사용 된다.이 임시 표 는 MySQL 에 의 해 자동 으로 생 성 되 고 일부 작업 의 중간 결 과 를 저장 합 니 다.이런 조작 은 최적화 단계 나 집행 단계 에 포 함 될 수 있다.이 내부 표 는 사용자 에 게 는 보이 지 않 지만 EXPLAIN 이나 SHOW STATUS 를 통 해 MYSQL 이 내부 임시 표를 사용 하여 어떤 작업 을 수행 하 는 데 도움 을 주 었 는 지 확인 할 수 있 습 니 다.내부 임시 표 는 SQL 문장의 최적화 과정 에서 매우 중요 한 역할 을 하고 MySQL 의 많은 조작 은 내부 임시 표 에 의존 하여 최적화 해 야 한다.그러나 내부 임시 표를 사용 하려 면 표 와 중간 데이터 의 액세스 대 가 를 만들어 야 하기 때문에 사용 자 는 SQL 문 구 를 쓸 때 임시 표를 사용 하지 않도록 해 야 한다.
내부 임시 표 는 두 가지 유형 이 있 습 니 다. 하 나 는 HEAP 임시 표 입 니 다. 이 임시 표 의 모든 데 이 터 는 메모리 에 존재 합 니 다. 이 표 의 조작 에 대해 서 는 IO 작업 이 필요 하지 않 습 니 다.다른 하 나 는 OnDisk 임시 표 인 데, 말 그대로 이 임시 표 는 데 이 터 를 디스크 에 저장 합 니 다.OnDisk 임시 표 는 중간 결과 가 비교적 큰 조작 을 처리 하 는 데 쓰 인 다.HEAP 임시 테이블 에 저 장 된 데이터 가 MAX 보다 크 면HEAP_TABLE_SIZE (자세 한 내용 은 MySQL 매 뉴 얼 의 시스템 변수 부분 을 참고 하 십시오), HEAP 임시 표 는 자동 으로 OnDisk 임시 표 로 변 환 됩 니 다.OnDisk 임시 표 는 5.7 에서 INTERNAL 을 통과 할 수 있 습 니 다.TMP_DISK_STORAGE_ENGINE 시스템 변 수 는 MyISAM 엔진 이나 InnoDB 엔진 을 선택 합 니 다.
이 글 은 주로 어떤 조작 이 내부 임시 표 에 이 용 될 수 있 는 지 를 소개 한다.만약 에 사용자 가 SQL 문 구 를 쓸 때 내부 임시 표를 최대한 적 게 사용 하여 조회 최 적 화 를 할 수 있다 면 조회 집행 의 효율 을 효과적으로 높 일 수 있다.
우선 표 t1 을 정의 합 니 다.
CREATE TABLE t1( a int, b int); INSERT INTO t1 VALUES(1,2),(3,4);
아래 의 모든 조작 은 표 t1 을 바탕 으로 예 를 들 었 다.
SQL 구문 에 SQL 사용 하기BUFFER_RESULT hint SQL_BUFFER_RESULT 는 주로 MySQL 이 표 의 자 물 쇠 를 가능 한 한 빨리 풀 도록 하 는 데 쓰 인 다.데이터 양 이 많 으 면 클 라 이언 트 에 데 이 터 를 보 내 는 데 시간 이 오래 걸 리 기 때문에 데 이 터 를 임시 표 에 버퍼 링 하면 읽 기 잠 금 시간 을 효과적으로 줄 일 수 있 습 니 다.예 를 들 면:
mysql> explain format=json select SQL_BUFFER_RESULT * from t1;
EXPLAIN
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "2.00"
},
"buffer_result": {
"using_temporary_table": true,
"table": {
"table_name": "t1",
"access_type": "ALL",
...
만약 SQL 문장 에 DERIVED 가 포함 되 어 있다 면TABLE。 5.7 에서 새로운 최적화 방식 을 채 택 했 기 때문에 우 리 는 set optimizer 를 사용 해 야 한다switch=’derived_merge = off '는 derived table 을 외부 Query 에 통합 하 는 것 을 금지 합 니 다.예 를 들 면:
mysql> explain format=json select * from (select * from t1) as tt;
EXPLAIN
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "2.40"
},
"table": {
"table_name": "tt",
"access_type": "ALL",
...
"materialized_from_subquery": {
"using_temporary_table": true,
...
만약 우리 가 시스템 표를 조회 한다 면 시스템 표 의 데 이 터 는 내부 임시 표 에 저 장 될 것 이다.현재 EXPLAIN 을 사용 하여 시스템 시트 데 이 터 를 읽 는 지 내부 임시 표 에 이용 해 야 하 는 지 확인 할 수 없 지만 SHOW STATUS 를 통 해 내부 임시 표 에 이용 되 었 는 지 확인 할 수 있 습 니 다.예 를 들 면:
mysql> select * from information_schema.character_sets;
mysql> show status like 'CREATE%';
DISTINCT 문구 가 최적화 되 지 않 으 면 DISTINCT 문구 가 GROUP BY 작업 으로 최적화 되 거나 UNIQUE INDEX 를 이용 하여 DISTINCT 를 제거 하면 내부 임시 표 가 사 용 됩 니 다.
mysql> explain format=json select distinct a from t1;
EXPLAIN
{
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "1.60"
},
"duplicates_removal": {
"using_temporary_table": true,
...
검색 에 ORDER BY 문구 가 있 고 최적화 되 지 않 습 니 다.다음 몇 가지 상황 은 내부 임시 표 캐 시 중간 데 이 터 를 이용 하여 중간 데 이 터 를 정렬 합 니 다.1) 연결 표 에 BNL (Batched Nestloop) / BKA (Batched Key Access) 를 사용 하면 다음 과 같다.
1) BNL 은 기본적으로 열 려 있다
mysql> explain format=json select * from t1, t1 as t2 order by t1.a;
EXPLAIN
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "22.00"
},
"ordering_operation": {
"using_temporary_table": true,
...
2)) BNL 을 끄 면 ORDER BY 는 filesort 를 직접 사용 합 니 다.
mysql> set optimizer_switch='block_nested_loop=off';
Query OK, 0 rows affected (0.00 sec)
mysql> explain format=json select * from t1, t1 as t2 order by t1.a;
EXPLAIN
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "25.00"
},
"ordering_operation": {
"using_filesort": true,
...
2) ORDER BY 의 열 은 실행 계획 의 첫 번 째 연결 표 의 열 에 속 하지 않 습 니 다.예 를 들 면:
mysql> explain format=json select * from t as t1, t as t2 order by t2.a;
EXPLAIN
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "25.00"
},
"ordering_operation": {
"using_temporary_table": true,
...
3) ORDER BY 의 표현 식 이 복잡 한 표현 식 이 라면.
그렇다면 어떤 ORDER BY 표현 식, MySQL 은 복잡 한 표현 식 이 라 고 생각 합 니까?
1)) 정렬 식 이 SP 또는 UDF 라면.예 를 들 면:
drop function if exists func1;
delimiter |
create function func1(x int)
returns int deterministic
begin
declare z1, z2 int;
set z1 = x;
set z2 = z1+2;
return z2;
end|
delimiter ;
explain format=json select * from t1 order by func1(a);
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "2.20"
},
"ordering_operation": {
"using_temporary_table": true,
..
2)) ORDER BY 의 열 은 집합 함 수 를 포함한다
실행 계획 을 간소화 하기 위해 저 희 는 INDEX 를 이용 하여 GROUP BY 문 구 를 최적화 합 니 다.예 를 들 면:
create index idx1 on t1(a);
explain format=json SELECt a FROM t1 group by a order by sum(a);
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "1.20"
},
"ordering_operation": {
"using_temporary_table": true,
"using_filesort": true,
"grouping_operation": {
"using_filesort": false,
...
drop index idx1 on t1;
3)) ORDER BY 의 열 에는 SCALAR SUBQUERY 가 포함 되 어 있 습 니 다. 물론 이 SCALAR SUBQUERY 는 최적화 되 지 않 았 습 니 다.예 를 들 면:
explain format=json select (select rand() from t1 limit 1) as a from t1 order by a;
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "1.20"
},
"ordering_operation": {
"using_temporary_table": true,
"using_filesort": true,
...
4) 조 회 는 ORDER BY 와 GROUP BY 문 구 를 가지 고 있 지만 두 문 구 는 열 이 다르다.
주의: 5.7 이 라면 sqlmode 는 비 only 로 설정full_group_by 모드, 그렇지 않 으 면 잘못 보고 할 수 있 습 니 다.
마찬가지 로 실행 계획 을 간소화 하기 위해 저 희 는 INDEX 를 이용 하여 GROUP BY 문 구 를 최적화 합 니 다.예 를 들 면:
set sql_mode='';
create index idx1 on t1(b);
explain format=json select t1.a from t1 group by t1.b order by 1;
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "1.40"
},
"ordering_operation": {
"using_temporary_table": true,
"using_filesort": true,
"grouping_operation": {
"using_filesort": false,
...
drop index idx1 on t1;
검색 이 GROUP BY 문 구 를 가지 고 있 고 최적화 되 지 않 는 다 면.아래 의 몇 가지 상황 은 내부 임시 테이블 캐 시 중간 데 이 터 를 이용 하여 중간 데 이 터 를 GROUP BY 로 진행 합 니 다.1) 연결 표 에 BNL (Batched Nestloop) / BKA (Batched Key Access) 를 사용 하면.예 를 들 면:
explain format=json select t2.a from t1, t1 as t2 group by t1.a;
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "8.20"
},
"grouping_operation": {
"using_temporary_table": true,
"using_filesort": true,
"cost_info": {
"sort_cost": "4.00"
...
2) 그룹 BY 의 열 이 실행 계획 의 첫 번 째 연결 표 에 속 하지 않 는 다 면.예 를 들 면:
explain format=json select t2.a from t1, t1 as t2 group by t2.a;
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "8.20"
},
"grouping_operation": {
"using_temporary_table": true,
"using_filesort": true,
"nested_loop": [
...
3) GROUP BY 구문 에서 사용 하 는 열 이 ORDER BY 구문 에서 사용 하 는 열 과 다르다 면.예 를 들 면:
set sql_mode='';
explain format=json select t1.a from t1 group by t1.b order by t1.a;
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "1.40"
},
"ordering_operation": {
"using_filesort": true,
"grouping_operation": {
"using_temporary_table": true,
"using_filesort": false,
...
4) 그룹 BY 가 ROLLUP 을 가지 고 있 고 다 중 표 외 연결 을 기반 으로 한다 면.예 를 들 면:
explain format=json select sum(t1.a) from t1 left join t1 as t2 on true group by t1.a with rollup;
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "7.20"
},
"grouping_operation": {
"using_temporary_table": true,
"using_filesort": true,
"cost_info": {
"sort_cost": "4.00"
},
...
5) GROUP BY 문 구 를 사용 하 는 열 이 SCALAR SUBQUERY 에서 나 왔 고 최적화 되 지 않 았 다 면.예 를 들 면:
explain format=json select (select avg(a) from t1) as a from t1 group by a;
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "3.40"
},
"grouping_operation": {
"using_temporary_table": true,
"using_filesort": true,
"cost_info": {
"sort_cost": "2.00"
},
...
IN 표현 식 을 semi - join 으로 변환 하여 최적화 1) semi - join 실행 방식 이 Materialization 이 라면:
set optimizer_switch='firstmatch=off,duplicateweedout=off';
explain format=json select * from t1 where a in (select b from t1);
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "5.60"
},
"nested_loop": [
{
"rows_examined_per_scan": 1,
"materialized_from_subquery": {
"using_temporary_table": true,
"query_block": {
"table": {
"table_name": "t1",
"access_type": "ALL",
...
2) semi - join 의 실행 방식 이 Duplicate Weedout 이 라면:
set optimizer_switch='firstmatch=off';
explain format=json select * from t1 where a in (select b from t1);
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "4.80"
},
"duplicates_removal": {
"using_temporary_table": true,
"nested_loop": [
{
...
검색 어 에 UNION 이 있 으 면 MySQL 은 내부 임시 표를 이용 하여 UNION 작업 의 중복 을 없 애 는 데 도움 을 줄 것 이다.예 를 들 면:
explain format=json select * from t1 union select * from t1;
| {
"query_block": {
"union_result": {
"using_temporary_table": true,
"table_name": "" ,
...
검색 어 를 다 중 표 로 업데이트 하면.여기 서 Explain 은 내부 임시 표 가 이용 되 는 것 을 볼 수 없 기 때문에 status 를 봐 야 합 니 다.예 를 들 면:
update t1, t1 as t2 set t1.a=3;
show status like 'CREATE%';
집합 함수 에 다음 과 같은 함수 가 포함 되 어 있 으 면 내부 임시 표 도 이용 된다.1) count (distinct *) 예:
explain format=json select count(distinct a) from t1;
2) group_concat 예:
explain format=json select group_concat(b) from t1;
한 마디 로 하면 위 에 10 가지 상황 이 열거 되 어 있 습 니 다. MySQL 은 내부 임시 표를 이용 하여 중간 결과 캐 시 를 합 니 다. 데이터 양 이 많 으 면 내부 임시 표 는 데 이 터 를 디스크 에 저장 합 니 다. 그러면 성능 에 영향 을 줄 수 있 습 니 다.가능 한 한 성능 손실 을 줄 이기 위해 서 우 리 는 상술 한 상황 의 발생 을 피해 야 한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
MySQL에서 JSON 인덱싱 - aarondfrancis사람들은 종종 MySQL로 JSON을 인덱싱할 수 없다고 말하지만 완전히 정확하지는 않습니다. MySQL로 JSON 열을 인덱싱하는 것은 완전히 가능합니다! 사람들은 종종 MySQL로 JSON을 인덱싱할 수 없다고 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.