中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在MySQL中對Group by進行優化

發布時間:2021-03-09 15:12:34 來源:億速云 閱讀:256 作者:Leah 欄目:開發技術

本篇文章為大家展示了怎么在MySQL中對Group by進行優化,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

一個標準的 Group by 語句包含排序、分組、聚合函數,比如 select a,count(*) from t group by a ;  這個語句默認使用 a 進行排序。如果 a 列沒有索引,那么就會創建臨時表來統計 a和 count(*),然后再通過 sort_buffer 按 a 進行排序。

標準的執行流程

結構:

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();

函數就是向 t1 中插入1000條語句,從(1,1,1) 到(1000,1000,1000)。

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

解析:

怎么在MySQL中對Group by進行優化

Using index,表示這個語句使用了覆蓋索引,選擇了索引 a,不需要回表;
Using temporary,表示使用了臨時表;
Using filesort,表示需要排序。

過程:

1、創建內存臨時表,表里有兩個字段 m 和 c,主鍵是 m;
2、掃描表 t1 的索引 a,依次取出葉子節點上的 id 值,計算 id%10 的結果,記為 x;
  1)如果臨時表中沒有主鍵為 x 的行,就插入一個記錄 (x,1);
  2)如果表中有主鍵為 x 的行,就將 x 這一行的 c 值加 1;

第2 步如果發現內存臨時表存儲的總字段長度到達參數 tmp_table_size 設置的大小,那么就會將內存臨時表升級為磁盤臨時表,然后重新開始遍歷計算。
3、遍歷完成后,再根據字段 m 做排序,得到結果集返回給客戶端。

怎么在MySQL中對Group by進行優化

最后的排序就是下圖虛線框中的操作,如果 sort_buffer 設置的大小不夠大,那么就會使用臨時表來輔助排序。

怎么在MySQL中對Group by進行優化

優化

未優化(也就是分組列沒有索引)的 group by 的總過程可以概括為:因為數據是無序的,所以需要創建臨時表,然后一個一個判斷屬于哪個分組,最后再根據分組列進行排序。所以,優化可以有兩個思路:

去掉排序

在明確返回的數據不需要排序的情況下,可以禁止排序,也就是將上面的語句改成 select a,count(*) from t group by a order by null。

順序排列

如果記錄都按照排序字段排序,那么數據就變成了下面的結構:

怎么在MySQL中對Group by進行優化

這樣在實際獲取要返回的字段或計算聚合函數時,只需要按順序依次訪問,等到列值變成下一個就知道當前組訪問結束,將之前統計的數據直接返回。這樣就避免了創建臨時表,同時排序也不需要使用 sort_buffer 進行額外排序。這樣就極大地提高了執行的效率。

實現

1、如果分組字段適合創建索引就直接為分組字段創建索引。

MySQL 5.7 版本支持了 generated column 機制,用來實現列數據的關聯更新。你可以用下面的方法創建一個列 z,然后在 z 列上創建一個索引(如果是 MySQL 5.6 及之前的版本,你也可以創建普通列和索引,來解決這個問題)

alter table t1 add column z int generated always as(id % 100), add index(z);

然后解析:

怎么在MySQL中對Group by進行優化

這時沒有用到臨時表和額外排序,所以性能提升。

2、如果分組字段不適合(使用率很低),那么可以使用 SQL_BIG_RESULT 來嘗試優化。

在 group by 語句中加入 SQL_BIG_RESULT 這個提示(hint),就可以告訴優化器:這個語句涉及的數據量很大,請直接用磁盤臨時表。MySQL 的優化器一看,磁盤臨時表是 B+ 樹存儲,存儲效率不如數組來得高。所以,既然使用SQL_BIG_RESULT來說明數據量很大,那從磁盤空間考慮,還是直接用數組來存吧。所以在使用 SQL_BIG_RESULT 后優化器會使用數組結構的磁盤臨時表。

但是如果在未達到磁盤臨時表的使用條件是不會使用磁盤臨時表的,也就是在 sort_buffer 空間能夠存儲要返回和排序的總字段長度時,就使用數組結構的 sort_buffer ,如果總字段超過 sort_buffer 大小,那么就再加上數組結構的磁盤臨時表來幫助排序。

那么在 sort_buffer 空間足夠的情況下, sort_buffer 內部就會對數據進行排序,這樣也就起到了索引的作用,

還是以上面的例子來看,使用 SQL_BIG_RESULT

alter table t1 add column z int generated always as(id % 100), add index(z);

具體過程如下:

1、初始化 sort_buffer,確定放入一個整型字段,記為 m;
2、掃描表 t1 的索引 a,依次取出里面的 id 值, 將 id%10 的值存入 sort_buffer 中;
3、掃描完成后,對 sort_buffer 的字段 m 做排序(如果 sort_buffer 內存不夠用,就會利用磁盤臨時文件輔助排序);
4、排序完成后,就得到了一個有序數組。

怎么在MySQL中對Group by進行優化

解析:

怎么在MySQL中對Group by進行優化

可以看到此時就沒有使用臨時表了,而是直接使用 sort_buffer 進行排序,這樣就省去了使用臨時表帶來的性能消耗。

上述內容就是怎么在MySQL中對Group by進行優化,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

虞城县| 太保市| 梅河口市| 合山市| 合江县| 宁陵县| 顺平县| 吉水县| 华坪县| 青龙| 鸡泽县| 荆门市| 宜良县| 西安市| 承德市| 扎赉特旗| 吴桥县| 汉阴县| 电白县| 洮南市| 宁晋县| 当阳市| 琼中| 河南省| 敦煌市| 南汇区| 新野县| 米脂县| 靖宇县| 海城市| 万载县| 潮安县| 璧山县| 白玉县| 井研县| 水富县| 金塔县| 合江县| 老河口市| 高安市| 汶上县|