MySQL什么時候會使用內部臨時表?


1.union執行過程

首先我們創建一個表t1

create table t1(id int primary key, a int, b int, index(a));
delimiter ;;
create procedure idata()
begin
  declare i int;
  set i=1;
  while(i<=1000)do
    insert into t1 values(i, i, i);
    set i=i+1;
  end while;
end;;
delimiter ;
call idata();

然后我們執行一下這條語句

explain select 1000 as f union (select id from t1 order by id desc limit 2)

首先說下union的語義,union的語義是取兩個結果的並集,重復的保留一行,然后我們來看下explain的結果,第二行的key=PRIMARY,說明用到了主鍵索引。

第三行的Extra的Using temporary說明用到了臨時表

 

下面我們看下這條語句的執行流程:

1.創建一個臨時表,只有f一個字段,且為主鍵

2.將1000這個數據插入臨時表

3.子查詢中步驟:

1.插入1000進入臨時表,因為主鍵沖突,插入失敗

2.插入第二行900,插入成功

4.將臨時表數據作為結果返回,並刪除臨時表

這個過程的流程圖如下:

如果我們把union改成union all,就不需要使用臨時表了,因為union all是重復的也保留,

大家可以看到extra這一列已經沒有了Using temporary

explain select 1000 as f union all (select id from t1 order by id desc limit 2)

2.group by執行過程

我們來看下面這條語句:

explain select id%10 as m, count(*) as c from t1 group by m;

可以看到explain結果

Using index(使用到了覆蓋索引a,不需要回表); Using temporary(用到了臨時表); Using filesort(對數據進行了排序)

這條語句的意思是將id%10進行分組統計,並按照m進行排序

執行流程如下:

1.創建臨時表,增加m,c字段,m是主鍵

2.計算id%10的結果記為x

3.如果臨時表里面沒有主鍵為x的行,則插入(x,1),如果有的話,就將該行的c值加1

4.遍歷完成后,按照m字段排序返回結果給客戶端

流程圖如下

接下來我們看下這條語句的執行結果

explain select id%10 as m, count(*) as c from t1 group by m

其實,如果我們不需要對查詢結果進行排序,我們可以加一個order by null

我們執行一下這條語句

explain select id%10 as m, count(*) as c from t1 group by m order by null

可以看到這里沒有進行排序,由於掃描是從表t的id是從1開始的,所以第一行是1

如果我們執行下列語句,會發生什么呢?

我們上面說的臨時表,其實是內存臨時表,如果我們把內存臨時表的容量改的比我們要查詢的數據的容量小,那么就會使用到磁盤臨時表,磁盤臨時表的默認引擎是innodb

et tmp_table_size=1024;
select id%100 as m, count(*) as c from t1 group by m order by null limit 10

  

group by 優化方法--直接排序

其實在上面的關於從內存臨時表轉化成磁盤臨時表是很浪費時間的,也就是說mysql,在執行過程中發現空間不夠了,在轉成磁盤臨時表,但是如果我們直接告訴mysql,我要查詢的數據很大,那么mysql優化器就會想到,既然你告訴我數據很大,那么我就直接用sort_buffer進行排序,如果sort_buffer內存不夠大,會用到磁盤臨時表輔助排序。

select SQL_BIG_RESULT id%100 as m, count(*) as c from t1 group by m;

小結一下:

1.如果我們不需要對統計結果進行排序,可以加上order by null省去排序流程。

2.盡量讓排序過程用上內存臨時表,可以通過適當調大tmp_table_size的值來避免用到磁盤臨時表。

3.如果數據量實在太大,使用SQL_BIG_RESULT告訴優化器,直接使用排序算法。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM