亚洲综合原千岁中文字幕_国产精品99久久久久久久vr_无码人妻aⅴ一区二区三区浪潮_成人h动漫精品一区二区三

主頁 > 知識庫 > MySQL group by語句如何優化

MySQL group by語句如何優化

熱門標簽:日照旅游地圖標注 廣東人工電話機器人 信陽穩定外呼系統運營商 南通自動外呼系統軟件 湖南人工外呼系統多少錢 石家莊電商外呼系統 申請外呼電話線路 百度地圖圖標標注中心 芒果電話機器人自動化

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

mysql> show create table t1\G
*************************** 1. row ***************************
    Table: t1
Create 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=utf8
1 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)

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

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:使用了內存臨時表
  • using filesort:使用了排序操作

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

對照上面這個表,我們不難發現,這個group by的語句執行流程是下面這樣的:

a、首先創建內存臨時表,內存表里有兩個字段m和c,主鍵是m;m是id%10,而c是統計的count(*) 個數

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

c、遍歷完成后,再根據字段m做排序,得到結果集返回給客戶端。(注意,這個排序的動作是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字樣已經不見了。再來看下結果:

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個結果,在內存臨時表中還可以放下,內存臨時表在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)

   當我們的結果足夠大,而內存臨時表不足以保存的時候,MySQL就會使用磁盤臨時表,整個訪問的速度就變得很慢了。那么針對group by操作,我們如何優化?

01

group by優化之索引

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

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

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

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

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

   上面的結構我們也不陌生,當我們以在某個數據列上創建索引的時候,這個列本身就是排序的,當group by是以這個列為條件的時候,那么這個過程就不需要排序,因為索引是自然排序的。為了實現這個優化,我們給表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: 0

mysql> 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之后的值,并且創建索引,再通過group by對這個z列進行分組,可以看到,結果中已經沒有臨時表了。

   所以,使用索引可以幫助我們去掉group by依賴的臨時表

02

group by優化---直接排序

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

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

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內存不夠用,就會利用磁盤臨時文件輔助排序);

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

e、根據有序數組,得到數組里面的不同值,以及每個值的出現次數。

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

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

1、如果語句執行過程可以一邊讀數據,一邊直接得到結果,是不需要額外內存的,否則就需要額外的內存,來保存中間結果;

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

以上就是MySQL group by語句如何優化的詳細內容,更多關于MySQL group by優化的資料請關注腳本之家其它相關文章!

您可能感興趣的文章:
  • MySQL優化GROUP BY(松散索引掃描與緊湊索引掃描)
  • MySQL優化GROUP BY方案
  • MySQL Group by的優化詳解

標簽:阿里 惠州 公主嶺 天津 呼和浩特 牡丹江 合肥 沈陽

巨人網絡通訊聲明:本文標題《MySQL group by語句如何優化》,本文關鍵詞  MySQL,group,語句,如何,優化,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《MySQL group by語句如何優化》相關的同類信息!
  • 本頁收集關于MySQL group by語句如何優化的相關信息資訊供網民參考!
  • 推薦文章
    欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 四虎影视久久| a级黄色毛片免费播放视频| 亚洲天堂免费| 国产成人精品综合在线| 国产不卡高清| 日日爽天天| 精品视频在线观看一区二区三区| 日韩av东京社区男人的天堂| 日本免费乱人伦在线观看| 欧美国产日韩精品| 久久精品大片| 国产麻豆精品免费视频| 美国一区二区三区| 夜夜操天天爽| 国产91精品露脸国语对白| 黄视频网站免费| 日韩在线观看网站| 精品视频在线看| 国产一区二区精品久久91| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 成人免费网站久久久| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 成人高清视频免费观看| 成人免费一级纶理片| 欧美日本二区| 韩国毛片免费| 精品久久久久久免费影院| 日韩一级黄色大片| 久久国产影院| 日韩一级黄色大片| 精品视频免费在线| 国产成人精品影视| 成人a大片高清在线观看| 日韩在线观看视频黄| 亚洲女初尝黑人巨高清在线观看| 九九精品在线| 免费一级生活片| 亚洲天堂免费观看| 欧美另类videosbestsex久久| 精品在线观看一区| 成人免费观看男女羞羞视频| 久久久成人网| 国产麻豆精品免费视频| 精品国产一区二区三区久久久狼| 色综合久久天天综线观看| 香蕉视频三级| 在线观看成人网| 国产一级生活片| 精品视频免费看| 国产a毛片| 国产综合91天堂亚洲国产| 日韩中文字幕在线亚洲一区 | 欧美爱色| 亚洲 激情| 国产麻豆精品| 毛片高清| 欧美国产日韩在线| 欧美国产日韩一区二区三区| 精品国产一级毛片| 亚洲爆爽| 国产亚洲男人的天堂在线观看| 国产不卡在线观看| 欧美另类videosbestsex高清 | 久久国产一久久高清| 国产麻豆精品视频| 国产亚洲男人的天堂在线观看| 午夜在线亚洲| 精品久久久久久免费影院| 久久国产影视免费精品| 精品国产一区二区三区精东影业 | 亚欧视频在线| 尤物视频网站在线观看| 二级特黄绝大片免费视频大片| 国产成人精品综合| 日本特黄特色aa大片免费| 成人a级高清视频在线观看| 国产成人精品影视| 日本在线不卡免费视频一区| 国产视频久久久| 日韩在线观看视频免费| 久久精品欧美一区二区| 国产成人女人在线视频观看| 99热热久久| 韩国毛片基地| 天天做日日爱夜夜爽| 日本在线www| 国产伦精品一区二区三区在线观看| 欧美国产日韩在线| 日日夜人人澡人人澡人人看免| 天天做日日干| 欧美激情一区二区三区在线 | 九九久久99| 99久久精品国产国产毛片| 国产麻豆精品免费密入口| 国产一区二区精品久久91| 99久久精品国产免费| 国产亚洲精品aaa大片| 成人高清护士在线播放| 高清一级毛片一本到免费观看| 日本伦理黄色大片在线观看网站| 日韩在线观看免费完整版视频| 可以免费在线看黄的网站| 99久久精品国产国产毛片| 色综合久久天天综合观看| 欧美爱爱网| 国产一区二区精品在线观看| 国产一区二区精品久久91| 成人影视在线观看| 久久精品免视看国产成人2021| 亚洲 男人 天堂| 999久久66久6只有精品| 国产不卡在线观看| 成人高清视频在线观看| 黄视频网站在线看| 国产韩国精品一区二区三区| 亚欧视频在线| 国产91丝袜高跟系列| 免费一级生活片| 久久99这里只有精品国产| 日本在线播放一区| 日韩中文字幕一区| 91麻豆国产| 国产不卡高清在线观看视频| 成人av在线播放| 九九精品影院| 久久成人综合网| 成人免费网站久久久| 韩国三级视频网站| 亚洲第一色在线| 午夜激情视频在线观看| 青青久在线视频| 午夜激情视频在线观看| 日本特黄特色aa大片免费| 夜夜操天天爽| 精品久久久久久免费影院| 青青久久国产成人免费网站| 黄视频网站免费看| 国产不卡高清在线观看视频| 四虎影视久久久| 亚洲 男人 天堂| 一级女人毛片人一女人| 美国一区二区三区| 日韩专区亚洲综合久久| 免费国产在线观看| 99色视频在线观看| 欧美大片毛片aaa免费看| 国产伦久视频免费观看视频| 国产不卡在线观看视频| 亚洲天堂在线播放| 日本特黄一级| 日本在线播放一区| 成人免费观看的视频黄页| 日韩欧美一二三区| 日韩专区亚洲综合久久| 亚洲精品中文字幕久久久久久| 欧美1区2区3区| 精品久久久久久综合网| 国产精品免费久久| 欧美大片毛片aaa免费看| 日本特黄特黄aaaaa大片| 九九久久国产精品大片| 一级毛片看真人在线视频| 青青久久国产成人免费网站| 麻豆网站在线看| 四虎精品在线观看| 人人干人人草| 四虎影视精品永久免费网站 | 中文字幕97| 国产视频久久久| 精品国产一区二区三区精东影业 | 精品国产一区二区三区久久久蜜臀| 黄视频网站免费看| 成人a大片高清在线观看| 欧美大片毛片aaa免费看| 一级女性全黄生活片免费| 亚洲第一色在线| 99热热久久| 欧美一级视频高清片| 一 级 黄 中国色 片| 午夜久久网| 午夜在线亚洲| 国产网站免费视频| 美女被草网站| 久久精品店| 麻豆网站在线看| 超级乱淫黄漫画免费| 91麻豆精品国产自产在线观看一区| 久久久久久久免费视频| 精品在线观看国产| 97视频免费在线观看| 国产成人精品综合在线| 99久久精品费精品国产一区二区| 精品久久久久久免费影院| 欧美激情一区二区三区中文字幕| 欧美激情一区二区三区在线播放 | 久久久久久久男人的天堂| 国产精品自拍在线观看| 免费国产一级特黄aa大片在线| 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 |