成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官:MySQL 使用 group by 語句時發現執行很慢,可能是什么原因?

數據庫 MySQL
group by 語句是非常好用的分組聚合函數,但如果使用不上覆蓋索引,效率可能會非常低,尤其是表中數據量比較大的情況下。可以參考本文的方法進行優化。

大家好,我是君哥。

使用 MySQL 時,group by 是我們經常會用到的分組語句,可以幫我們做各種聚合統計工作。但有時候會發現 group by 語句執行很慢,可能是什么原因呢?今天來介紹一下。

1.簡介

下面我們創建一張員工表:

CREATE TABLE`db_staff` (
`staff_id` i  nt(8) NOTNULL AUTO_INCREMENT COMMENT'員工編號',
`id_no`varchar(20) DEFAULTNULLCOMMENT'員工姓名',
`name`varchar(20) DEFAULTNULLCOMMENT'員工姓名',
`email`varchar(200) DEFAULTNULLCOMMENT'郵件地址',
`age`tinyint(3) DEFAULTNULLCOMMENT'年齡',
`sex`tinyint(1) DEFAULT'0'COMMENT'性別,0:男 1:女',
`address`varchar(300) DEFAULTNULLCOMMENT'家庭住址',
`create_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'創建時間',
`update_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'更新時間',
  PRIMARY KEY (`staff_id`),
KEY`union_idno_name_email` (`id_no`,`name`,`email`)
) ENGINE=InnoDB AUTO_INCREMENT=1001DEFAULTCHARSET=utf8

然后往表中插入 20 條數據:

圖片圖片

我們用一個簡單的分組函數,對年齡(age)進行分組

SELECT age,COUNT(age) ca FROM db_staff GROUP BY age;

查詢結果如下圖:

圖片圖片

可以看到,使用 group by 語句非常方便地對各年齡的員工數量做了統計。

2.查詢分析

那使用 group by 語句時為什么會執行慢呢? 我們看一下這條 sql 的執行計劃:

圖片圖片

從執行計劃可以看到,這條 sql 沒有走索引,并且使用到了臨時表(Using temporary)和排序(Using filesort)。

注意:filesort 很容易被理解成文件排序,其實不然,MySQL 所有不走索引的排序統稱為 filesort,即使數據完全在內存中排序,執行計劃 Extra 也會顯示 Using filesort。

下面看一下這個語句的執行流程: 

  • 創建一個內存臨時表,表里有兩個字段 age 和 ca,其中 age 字段是主鍵。
  • 掃描要查詢的表中記錄,取出 age 字段;
  • 如果臨時表中有這條 age(比如 ag=20) 的記錄,則 ca 值加 1,否則插入一條新的記錄,比如(age=30,ca=1);
  • 4根據 age 做排序,將結果返回。

3.如何優化

3.1 是否需要排序

在 MySQL 8.0 以前,GROUP BY 默認是會對分組字段做排序的,即使 sql 中沒寫 ORDER BY,也會排序。

而且,內存中排序要用到 sort_buffer,如果 sort_buffer 內存不夠,就需要依靠磁盤臨時表輔助排序,非常影響性能。

如果想要 sql 語句不排序,可以在 sql 尾部加 order by null,修改后的 sql 如下:

SELECT age,COUNT(age) ca FROM db_staff GROUP BY age ORDER BY NULL;

修改后再看執行計劃,Extra 字段中沒有了 Using filesort。

3.2 走索引

對分組字段加索引是最好的優化方法。我們對 age 字段加一個索引:

ALTER TABLE db_staff ADD KEY age_idx(age);

修改后我們再看一下執行計劃

圖片圖片

給 age 字段加上索引后,就不走臨時表和 filesort 了。

3.3 磁盤臨時表

前面提到過,如果 sort_buffer 內存不夠,就需要依靠磁盤臨時表輔助排序。為了避免使用磁盤臨時表,可以考慮減小結果集,或者臨時增加 sort_buffer 大小。

對于內存臨時表也一樣,如果內存不夠,就需要依靠磁盤臨時表,可以通過修改 tmp_table_size 參數來避免使用磁盤臨時表。

3.4 應用層分組

對于非常復雜的聚合,可以考慮在應用層通過代碼分批處理,利用多線程并發處理能力提高效率。這樣可以減小數據庫壓力。

3.5 物理視圖

對于超大表,可以考慮增加物理視圖來代替 sql 分組,或者使用大數據工具。這樣可以同時減少數據庫和應用服務的壓力,但也帶來了額外維護物理視圖的工作量,結果集時效性低也不高。

4.總結

group by 語句是非常好用的分組聚合函數,但如果使用不上覆蓋索引,效率可能會非常低,尤其是表中數據量比較大的情況下。可以參考本文的方法進行優化。


責任編輯:武曉燕 來源: 君哥聊技術
相關推薦

2025-06-10 04:00:00

MySQL數據主庫

2020-12-16 10:49:56

谷歌系統系統癱瘓

2022-06-23 12:52:53

數據庫方案

2025-03-05 00:01:00

ReduxReact

2024-09-19 08:42:43

2009-03-11 11:12:24

2022-04-25 08:20:22

離職公司996

2021-06-03 08:55:54

分布式事務ACID

2023-02-04 07:34:12

URLIP身份定位

2025-06-13 02:10:00

MySQL大表業務場景

2010-08-27 10:53:14

面試

2024-04-19 08:23:06

2023-01-18 10:35:49

MySQL數據庫

2023-12-27 18:16:39

MVCC隔離級別幻讀

2024-11-19 15:13:02

2025-04-16 00:00:01

JWT客戶端存儲加密令

2024-02-22 09:19:52

2021-09-07 10:44:33

Java 注解開發

2016-03-10 20:42:09

2022-01-11 08:39:49

服務器速度服務器中毒
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲社区在线 | 天天干视频 | 午夜性色a√在线视频观看9 | 日韩影院在线观看 | 久久精品亚洲国产奇米99 | 色综合色综合 | 欧美成人精品一区二区男人看 | 日韩视频一区二区三区 | 亚洲日日夜夜 | 99精品99久久久久久宅男 | 欧美黄色性生活视频 | 亚洲天堂一区二区 | www久久99 | 国产日韩一区二区三区 | 91精品久久久久久久久99蜜臂 | 亚洲网在线 | 成人深夜福利 | 亚洲不卡视频 | 北条麻妃国产九九九精品小说 | 欧美一级三级在线观看 | 久久精品亚洲精品国产欧美 | 欧美亚洲在线 | 国产成人精品免高潮在线观看 | 日韩欧美专区 | 亚洲另类自拍 | 欲色av | 青青久久 | 国产乱人伦精品一区二区 | 久久精品中文字幕 | 一区二区免费在线 | 在线一区二区观看 | 五月激情综合网 | 91亚洲国产亚洲国产 | 久久99精品久久久久久 | 一区二区免费 | 亚洲 欧美 另类 综合 偷拍 | 久热久热 | 综合国产| 九九热在线视频观看这里只有精品 | 不卡一二三区 | 色婷婷精品 |