日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

MySQL group by語句如何優(yōu)化

瀏覽:144日期:2023-10-09 15:22:43

在MySQL中,新建立一張表,該表有三個字段,分別是id,a,b,插入1000條每個字段都相等的記錄,如下:

mysql> show create table t1G*************************** 1. row *************************** Table: t1Create Table: CREATE TABLE `t1` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `a` (`a`)) ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec)mysql> select * from t1 limit 10;+----+------+------+| id | a | b |+----+------+------+| 1 | 1 | 1 || 2 | 2 | 2 || 3 | 3 | 3 || 4 | 4 | 4 || 5 | 5 | 5 || 6 | 6 | 6 || 7 | 7 | 7 || 8 | 8 | 8 || 9 | 9 | 9 || 10 | 10 | 10 |+----+------+------+10 rows in set (0.00 sec)

當我們執(zhí)行下面包含group by的SQL時,查看執(zhí)行計劃,可以看到:

mysql> explain select id%10 as m, count(*) as c from t1 group by m limit 10;+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------+| 1 | SIMPLE | t1 | NULL | index | PRIMARY,a | a | 5 | NULL | 1000 | 100.00 | Using index; Using temporary; Using filesort |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------+1 row in set, 1 warning (0.00 sec)

最后面有:

using index:覆蓋索引 using temporary:使用了內(nèi)存臨時表 using filesort:使用了排序操作

為了更好的理解這個group by語句的執(zhí)行過程,我畫一個圖來表示:

MySQL group by語句如何優(yōu)化

對照上面這個表,我們不難發(fā)現(xiàn),這個group by的語句執(zhí)行流程是下面這樣的:

a、首先創(chuàng)建內(nèi)存臨時表,內(nèi)存表里有兩個字段m和c,主鍵是m;m是id%10,而c是統(tǒng)計的count(*) 個數(shù)

b、掃描表t1的索引a,依次取出葉子節(jié)點上的id值,計算id%10的結(jié)果,記為x;此時如果臨時表中沒有主鍵為x的行,就插入一個記錄(x,1);如果表中有主鍵為x的行,就將x這一行的c值加1;

c、遍歷完成后,再根據(jù)字段m做排序,得到結(jié)果集返回給客戶端。(注意,這個排序的動作是group by自動添加的。)

如果我們不想讓group by語句幫我們自動排序,可以添加上order by null在語句的末尾,這樣就可以去掉order by之后的排序過程了。如下:

mysql> explain select id%10 as m, count(*) as c from t1 group by m order by null;+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+------------------------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+------------------------------+| 1 | SIMPLE | t1 | NULL | index | PRIMARY,a | a | 5 | NULL | 1000 | 100.00 | Using index; Using temporary |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+------------------------------+1 row in set, 1 warning (0.00 sec)

可以看到,explain最后面的using filesort字樣已經(jīng)不見了。再來看下結(jié)果:

mysql> select id%10 as m, count(*) as c from t1 group by m;+------+-----+| m | c |+------+-----+| 0 | 100 || 1 | 100 || 2 | 100 || 3 | 100 || 4 | 100 || 5 | 100 || 6 | 100 || 7 | 100 || 8 | 100 || 9 | 100 |+------+-----+10 rows in set (0.00 sec)mysql> select id%10 as m, count(*) as c from t1 group by m order by null;+------+-----+| m | c |+------+-----+| 1 | 100 || 2 | 100 || 3 | 100 || 4 | 100 || 5 | 100 || 6 | 100 || 7 | 100 || 8 | 100 || 9 | 100 || 0 | 100 |+------+-----+10 rows in set (0.00 sec)

當我們不加order by null的時候,group by會自動為我們進行排序,所以m=0的記錄會在第一條的位置,如果我們加上order by null,那么group by就不會自動排序,那么m=0的記錄就在最后面了。

我們當前這個語句,表t1中一共有1000條記錄,對10取余,只有10個結(jié)果,在內(nèi)存臨時表中還可以放下,內(nèi)存臨時表在MySQL中,通過tmp_table_size來控制。

mysql> show variables like '%tmp_table%';+----------------+----------+| Variable_name | Value |+----------------+----------+| max_tmp_tables | 32 || tmp_table_size | 39845888 |+----------------+----------+2 rows in set, 1 warning (0.00 sec)

當我們的結(jié)果足夠大,而內(nèi)存臨時表不足以保存的時候,MySQL就會使用磁盤臨時表,整個訪問的速度就變得很慢了。那么針對group by操作,我們?nèi)绾蝺?yōu)化?

01

group by優(yōu)化之索引

從上面的描述中不難看出,group by進行分組的時候,創(chuàng)建的臨時表都是帶一個唯一索引的。如果數(shù)據(jù)量很大,group by的執(zhí)行速度就會很慢,要想優(yōu)化這種情況,還得分析為什么group by 需要臨時表?

這個問題其實是因為group by的邏輯是統(tǒng)計不同的值出現(xiàn)的次數(shù),由于每一行記錄做group by之后的結(jié)果都是無序的,所以就需要一個臨時表存儲這些中間結(jié)果集。如果我們的所有值都是排列好的,有序的,那情況會怎樣呢?

例如,我們有個表的記錄id列是:

0,0,0,1,1,2,2,2,2,3,4,4,

當我們使用group by的時候,就直接從左到右,累計相同的值即可。這樣就不需要臨時表了。

上面的結(jié)構(gòu)我們也不陌生,當我們以在某個數(shù)據(jù)列上創(chuàng)建索引的時候,這個列本身就是排序的,當group by是以這個列為條件的時候,那么這個過程就不需要排序,因為索引是自然排序的。為了實現(xiàn)這個優(yōu)化,我們給表t1新增一個列z,如下:

mysql> alter table t1 add column z int generated always as(id % 10), add index(z);Query OK, 0 rows affected (0.02 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> select z as m, count(*) as c from t1 group by z;+------+-----+| m | c |+------+-----+| 0 | 100 || 1 | 100 || 2 | 100 || 3 | 100 || 4 | 100 || 5 | 100 || 6 | 100 || 7 | 100 || 8 | 100 || 9 | 100 |+------+-----+10 rows in set (0.00 sec)mysql> explain select z as m, count(*) as c from t1 group by z;+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------------+| 1 | SIMPLE | t1 | NULL | index | z | z | 5 | NULL | 1000 | 100.00 | Using index |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------------+1 row in set, 1 warning (0.00 sec)

我們新增字段z,z的值是id%10之后的值,并且創(chuàng)建索引,再通過group by對這個z列進行分組,可以看到,結(jié)果中已經(jīng)沒有臨時表了。

所以,使用索引可以幫助我們?nèi)サ鬵roup by依賴的臨時表

02

group by優(yōu)化---直接排序

如果我們已經(jīng)知道表的數(shù)據(jù)量特別大,內(nèi)存臨時表肯定不足以容納排序的時候,其實我們可以通過告知group by進行磁盤排序,而直接跳過內(nèi)存臨時表的排序過程。

其實在MySQL中是有這樣的方法的:在group by語句中加入SQL_BIG_RESULT這個提示(hint),就可以告訴優(yōu)化器:這個語句涉及的數(shù)據(jù)量很大,請直接用磁盤臨時表。當我們使用這個語句的時候,MySQL將自動利用數(shù)組的方法來組織磁盤臨時表中的字段,而不是我們所周知的B+樹。關(guān)于這個知識點,這里給出官方文檔的介紹:

SQL_BIG_RESULT or SQL_SMALL_RESULT can be used with GROUP BY or DISTINCT to tell the optimizer that the result set has many rows or is small, respectively. For SQL_BIG_RESULT, MySQL directly uses disk-based temporary tables if they are created, and prefers sorting to using a temporary table with a key on the GROUP BY elements. For SQL_SMALL_RESULT, MySQL uses in-memory temporary tables to store the resulting table instead of using sorting. This should not normally be needed.

整個group by的處理過程將會變成:

a、初始化sort_buffer,確定放入一個整型字段,記為m;

b、掃描表t1的索引a,依次取出里面的id值, 將 id%100的值存入sort_buffer中;

c、掃描完成后,對sort_buffer的字段m做排序(如果sort_buffer內(nèi)存不夠用,就會利用磁盤臨時文件輔助排序);

d、排序完成后,就得到了一個有序數(shù)組。類似0,0,0,1,1,2,2,3,3,3,4,4,4,4這樣

e、根據(jù)有序數(shù)組,得到數(shù)組里面的不同值,以及每個值的出現(xiàn)次數(shù)。

昨天的文章中我們分析了union 語句會使用臨時表,今天的內(nèi)容我們分析了group by語句使用臨時表的情況,那么MySQL究竟什么時候會使用臨時表呢?

MySQL什么時候會使用內(nèi)部臨時表?

1、如果語句執(zhí)行過程可以一邊讀數(shù)據(jù),一邊直接得到結(jié)果,是不需要額外內(nèi)存的,否則就需要額外的內(nèi)存,來保存中間結(jié)果;

2、如果執(zhí)行邏輯需要用到二維表特性,就會優(yōu)先考慮使用臨時表。比如union需要用到唯一索引約束, group by還需要用到另外一個字段來存累積計數(shù)。

以上就是MySQL group by語句如何優(yōu)化的詳細內(nèi)容,更多關(guān)于MySQL group by優(yōu)化的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产毛片精品| 国际精品欧美精品| 日韩精品一二三| 日本一区免费网站| 国产九九精品| 日韩另类视频| 亚洲婷婷在线| 婷婷综合福利| 精品淫伦v久久水蜜桃| 神马午夜在线视频| 丝袜美腿亚洲色图| 国产精品地址| 久久国产欧美| 日韩精品久久久久久| 免费日韩成人| 久久久久网站| 欧美日韩精品一区二区三区在线观看| 精品国产一区二| 久久国产日韩欧美精品| 久久久久久美女精品| 亚洲精品系列| 国产传媒在线| 久久亚洲色图| jizzjizz中国精品麻豆| 亚洲香蕉久久| 国产中文在线播放| 亚洲青青久久| 欧美精品高清| 国产午夜精品一区在线观看| 亚洲高清不卡| 久久精品国产一区二区| 日韩中文字幕不卡| 国产不卡精品| 亚洲不卡视频| 欧美日韩一二三四| 国产精品啊啊啊| 视频一区视频二区中文| 久久中文在线| 日本不卡的三区四区五区| 999久久久精品国产| 国产一卡不卡| 亚洲激情av| 超碰在线99| 国产日韩一区二区三区在线| 日韩一级不卡| 国产精品蜜芽在线观看| 日韩av一区二| 国产精品毛片| 日韩av福利| 欧美一区二区三区久久| 一区在线免费| 日韩欧美综合| 欧美精品中文字幕亚洲专区| 亚洲一区二区三区高清| 日韩在线观看| 国产精品theporn| 日韩精品成人| 香蕉精品999视频一区二区| 欧产日产国产精品视频| 国产精品美女在线观看直播| 亚洲永久精品唐人导航网址| 久久亚洲国产| 日韩欧美一区免费| 欧美激情日韩| 欧美一区成人| 日韩欧美三区| 亚洲在线久久| 99久久久久国产精品| 久久精品国产久精国产| 国产亚洲精品精品国产亚洲综合| 亚洲视频电影在线| 国产精品毛片在线看| 激情偷拍久久| 999久久久91| 亚洲v在线看| 亚洲综合在线电影| 日韩综合精品| 日韩不卡在线| 桃色一区二区| 色爱av综合网| 欧美二三四区| 青青青免费在线视频| 国产精品免费不| 国产欧美一级| 91久久在线| 狠狠爱www人成狠狠爱综合网| 99久久视频| 激情婷婷久久| 亚洲欧洲午夜| 国产亚洲福利| 丝袜a∨在线一区二区三区不卡| 好看不卡的中文字幕| 91高清一区| 亚洲深夜影院| 亚洲免费网址| 免费在线观看成人| 亚洲乱亚洲高清| 亚洲伊人影院| 色综合视频一区二区三区日韩| 亚洲开心激情| 日本综合视频| 国产欧美一区二区精品久久久 | 欧美在线观看天堂一区二区三区| 亚洲天堂日韩在线| 天堂俺去俺来也www久久婷婷| 日韩精品欧美成人高清一区二区| 91精品福利观看| 国产精品嫩模av在线| 国产精品美女在线观看直播| 国产精品三级| 精品一区二区三区视频在线播放 | 欧美日韩国产观看视频| 久久精品一区二区不卡| 午夜欧美视频| 亚洲毛片视频| 国产黄色一区| 色黄视频在线观看| 九九久久电影| 亚洲精品第一| 欧美黄色一区| 肉色欧美久久久久久久免费看| 精品在线91| 视频在线在亚洲| 日韩高清不卡一区二区| 亚洲精品影视| 欧美在线不卡| 国产精品a级| 精品精品99| 中文字幕成在线观看| 日韩毛片视频| 亚洲精品一区二区妖精| 亚洲精品1区| 亚洲综合中文| 久久国产乱子精品免费女| 欧美国产免费| 精品日韩视频| 欧美黑人巨大videos精品| 综合激情一区| 日产精品一区二区| 亚洲精品国产偷自在线观看| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 蜜桃久久av一区| 日本成人一区二区| 精品久久97| 亚洲一级在线| 国产剧情一区二区在线观看| 精品免费av在线| 亚洲精品精选| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 亚洲精品乱码| 精品国产亚洲日本| 亚洲综合日韩| 久久不卡国产精品一区二区| 日本精品不卡| 日韩专区精品| 亚洲综合专区| 精品国产精品久久一区免费式 | 国产suv精品一区二区四区视频| 激情五月综合| 久久成人av| 国产va免费精品观看精品视频| 美女网站视频一区| 三级在线观看一区二区| 国产精品xvideos88| 91精品在线观看国产| 亚洲我射av| 精品日本视频| 中文欧美日韩| 欧美精品导航| 欧美中文字幕一区二区| 亚洲一区二区三区四区电影| 久久久精品国产**网站| 国产一区清纯| 久久激五月天综合精品| 91亚洲国产| 免费精品视频在线| 日韩中文欧美| 国产精品扒开腿做爽爽爽软件| 国产精品日韩欧美一区| 福利在线免费视频| 日韩精品a在线观看91| 大香伊人久久精品一区二区| 亚洲一区亚洲| 精品三级久久久| 丝袜美腿亚洲一区二区图片| 麻豆成人91精品二区三区| 亚洲精品麻豆| 99久久精品费精品国产| 精品一区av| 日韩av一区二| 香蕉成人久久| 色88888久久久久久影院| 久久久91麻豆精品国产一区| 婷婷综合福利| 欧美女激情福利| 欧美日韩精品免费观看视完整 | 亚洲一区日本| 999精品色在线播放| 国产传媒在线观看| 免费日韩一区二区三区|