mysql 分组查询原理,MySQL分組查詢Group By實現原理詳解

由於GROUP BY 實際上也同樣會進行排序操作,而且與ORDER BY 相比,GROUP BY 主要只是多了排序之后的分組操作。當然,如果在分組的時候還使用了其他的一些聚合函數,那么還需要一些聚合函數的計算。所以,在GROUP BY 的實現過程中,與 ORDER BY 一樣也可以利用到索引。

在MySQL 中,GROUP BY 的實現同樣有多種(三種)方式,其中有兩種方式會利用現有的索引信息來完成 GROUP BY,另外一種為完全無法使用索引的場景下使用。下面我們分別針對這三種實現方式做一個分析。

1、使用松散(Loose)索引掃描實現 GROUP BY

何謂松散索引掃描實現 GROUP BY 呢?實際上就是當 MySQL 完全利用索引掃描來實現 GROUP BY 的時候,並不需要掃描所有滿足條件的索引鍵即可完成操作得出結果。

下面我們通過一個示例來描述松散索引掃描實現 GROUP BY,在示例之前我們需要首先調整一下 group_message 表的索引,將 gmt_create 字段添加到 group_id 和 user_id 字段的索引中:

然后再看如下 Query 的執行計划:

我們看到在執行計划的 Extra 信息中有信息顯示“Using index for group-by”,實際上這就是告訴我們,MySQL Query Optimizer 通過使用松散索引掃描來實現了我們所需要的 GROUP BY 操作。

下面這張圖片描繪了掃描過程的大概實現:

2e4db0dba005debf42eda4527aae6e80.png

要利用到松散索引掃描實現 GROUP BY,需要至少滿足以下幾個條件:

◆GROUP BY 條件字段必須在同一個索引中最前面的連續位置;

◆在使用GROUP BY 的同時,只能使用 MAX 和 MIN 這兩個聚合函數;

◆如果引用到了該索引中 GROUP BY 條件之外的字段條件的時候,必須以常量形式存在;

為什么松散索引掃描的效率會很高?

因為在沒有WHERE子句,也就是必須經過全索引掃描的時候, 松散索引掃描需要讀取的鍵值數量與分組的組數量一樣多,也就是說比實際存在的鍵值數目要少很多。而在WHERE子句包含范圍判斷式或者等值表達式的時候, 松散索引掃描查找滿足范圍條件的每個組的第1個關鍵字,並且再次讀取盡可能最少數量的關鍵字。

2.使用緊湊(Tight)索引掃描實現 GROUP BY

緊湊索引掃描實現 GROUP BY 和松散索引掃描的區別主要在於他需要在掃描索引的時候,讀取所有滿足條件的索引鍵,然后再根據讀取惡的數據來完成 GROUP BY 操作得到相應結果。

這時候的執行計划的 Extra 信息中已經沒有“Using index for group-by”了,但並不是說 MySQL 的 GROUP BY 操作並不是通過索引完成的,只不過是需要訪問 WHERE 條件所限定的所有索引鍵信息之后才能得出結果。這就是通過緊湊索引掃描來實現 GROUP BY 的執行計划輸出信息。

下面這張圖片展示了大概的整個執行過程:

8dcc6d5bb1aea75a3d5f665c06a986a7.png

在 MySQL 中,MySQL Query Optimizer 首先會選擇嘗試通過松散索引掃描來實現 GROUP BY 操作,當發現某些情況無法滿足松散索引掃描實現 GROUP BY 的要求之后,才會嘗試通過緊湊索引掃描來實現。

當 GROUP BY 條件字段並不連續或者不是索引前綴部分的時候,MySQL Query Optimizer 無法使用松散索引掃描,設置無法直接通過索引完成 GROUP BY 操作,因為缺失的索引鍵信息無法得到。但是,如果 Query 語句中存在一個常量值來引用缺失的索引鍵,則可以使用緊湊索引掃描完成 GROUP BY 操作,因為常量填充了搜索關鍵字中的“差距”,可以形成完整的索引前綴。這些索引前綴可以用於索引查找。而如果需要排序GROUP BY結果,並且能夠形成索引前綴的搜索關鍵字,MySQL還可以避免額外的排序操作,因為使用有順序的索引的前綴進行搜索已經按順序檢索到了所有關鍵字。

3.使用臨時表實現 GROUP BY

MySQL 在進行 GROUP BY 操作的時候要想利用所有,必須滿足 GROUP BY 的字段必須同時存放於同一個索引中,且該索引是一個有序索引(如 Hash 索引就不能滿足要求)。而且,並不只是如此,是否能夠利用索引來實現 GROUP BY 還與使用的聚合函數也有關系。

前面兩種 GROUP BY 的實現方式都是在有可以利用的索引的時候使用的,當 MySQL Query Optimizer 無法找到合適的索引可以利用的時候,就不得不先讀取需要的數據,然后通過臨時表來完成 GROUP BY 操作。

這次的執行計划非常明顯的告訴我們 MySQL 通過索引找到了我們需要的數據,然后創建了臨時表,又進行了排序操作,才得到我們需要的 GROUP BY 結果。整個執行過程大概如下圖所展示:

40a9c0ce5a689d620493ff5c6455e7cd.png

當 MySQL Query Optimizer 發現僅僅通過索引掃描並不能直接得到 GROUP BY 的結果之后,他就不得不選擇通過使用臨時表然后再排序的方式來實現 GROUP BY了。

在這樣示例中即是這樣的情況。 group_id 並不是一個常量條件,而是一個范圍,而且 GROUP BY 字段為 user_id。所以 MySQL 無法根據索引的順序來幫助 GROUP BY 的實現,只能先通過索引范圍掃描得到需要的數據,然后將數據存入臨時表,然后再進行排序和分組操作來完成 GROUP BY。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/533201.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql 执行计划详解,Mysql中的explain执行计划详解(1)

创建一个表test_explain,并添加入下的数据mysql> create table test_explain( a int primary key, b int);Query OK, 0 rows affected (0.09 sec)mysql> insert into test_explain value(1,1),(2,2),(3,3),(4,4),(5,5);explian中的type字段:表示m…

mac php命令行模式,phpstorm分别在Mac和Windows下启动命令行,并启用ssh

Mac:在terminal下运行 sudo -i 输入密码 就可以用ssh IP:端口 命令行登录了DAssist是一个命令行开发辅助,可直接在系统命令行工具中使用,Linux和MacOS等自带命令终端的系统好说,windows下也有cmd和powerShell。那么如何结合开发IDE工具进行…

matlab 价格统计,matlab中的金融数据统计

1.均匀分布随机数生成函数unidrnd(N,m,n)N生成1到N之间的一个随机数,确定输出矩阵m行,n列。2.生成连续均匀分布的随机数unifrnd(A,B,m,n)A,B表示上下界。3.生成正态分布随机数normrnd(mu,sigma,m,n)mu均值,…

php访问js文件不存在,php文件里js不能被执行

我想把上传文件路径返回到前端保存&#xff0c;但是后台php文件里的js没有执行&#xff0c;前台input标签里的value值一直为空后台acceptfile.php代码如下:<?php if(!isset($_REQUEST[filename])){exit(No file);}else{$upload_path dirname(__FILE__)./audio;date_defaul…

php 零宽断言,正则表达式之零宽断言实例详解【基于PHP】

这篇文章主要介绍了正则表达式之零宽断言,简单介绍了零宽断言的概念、分类及php实现技巧与相关注意事项,需要的朋友可以参考下本文实例讲述了正则表达式之零宽断言。分享给大家供大家参考&#xff0c;具体如下&#xff1a;前言之前我曾写了一篇关于正则表达式的文章(//www.jb51…

python 逻辑回归准确率是1,Python利用逻辑回归模型解决MNIST手写数字识别问题详解...

本文实例讲述了Python利用逻辑回归模型解决MNIST手写数字识别问题。分享给大家供大家参考&#xff0c;具体如下&#xff1a;1、MNIST手写识别问题MNIST手写数字识别问题&#xff1a;输入黑白的手写阿拉伯数字&#xff0c;通过机器学习判断输入的是几。可以通过TensorFLow下载MN…

php面试题接口方面,php面试题6 - osc_xb4v1nhl的个人空间 - OSCHINA - 中文开源技术交流社区...

php面试题6一、总结二、php面试题6写出你认为语言中的高级函数:1)preg_replace()2)preg_match()3) ignore_user_abort()4) debug_backtrace()5) date_default_timezone_set(“PRC”)6) get_class_methods() 得到类的方法名的数组7) preg_split() 字符串分割成数组8)json_encode…

轨道车辆垂向振动Matlab建模与仿真,基于matlab/simulink的车辆建模与故障分析

随着铁路行业高速发展,列车运行速度逐渐提高,铁路安全越来越受到人们的重视,如何保证铁道车辆运行安全及其故障监测成为一个亟待解决的重大课题。客车车辆在结构上的故障主要有一系弹簧断裂、减振器失效、空气弹簧漏气、高圆弹簧断裂、车轮踏面擦伤、轴承故障以及蛇形减震器故障…

关于php的问题有哪些,关于PHP的报错问题?

关于这个报错的表格我不知到怎么去做&#xff0c;下面的是代码&#xff1a;header(content-type:text/html;charsetutf-8);session_start();include_once ../include/conf.php;include_once ../include/func.php;include_once ../include/mysql.func.php;check_login();$pageSi…

oracle消耗内存的查询,在AIX中计算ORACLE消耗的私有内存总数

一早就收到兄弟伙发的QQ信息&#xff0c;关于aix中oracle内存计算的内容The RSS number is equal to the sum of the number of working-segment pages in memory times 4 andthe code-segment pages in memory times 4.The TRS number is equal to just the code-segment page…

php读取ds18b20,DS18B20_单总线协议

.H文件#ifndef _ONEWIRE_H#define _ONEWIRE_H#include "STC15F2K60S2.H"#include #define OW_SKIP_ROM 0xcc#define DS18B20_CONVERT 0x44#define DS18B20_READ 0xbe//IC引脚定义sbit DQ P1^4;//函数声明extern void Delay_OneWire(unsigned int t);extern void Wri…

oracle官方文档查看方法,oracle官方文档_查看初始化参数(举例)

深蓝的blog&#xff1a;http://blog.csdn.net/huangyanlong/article/details/46864217记录了一下&#xff0c;使用oracle11g联机文档&#xff0c;查看初始化参数的步骤。如果想查看&#xff0c;可以修改的初始化参数的概念信息&#xff0c;可以点击“ChangingParameter Values …

matlab usewhitebg,Matlab的:geo​​show的網格和框架

對於問題1和問題2&#xff0c;原因是軸總是在圖的後面。因此&#xff0c;一種解決方案是在當前的軸上添加新軸並顯示網格&#xff0c;框和自定義刻度。對於問題3&#xff0c;我使用regexprep以取代S後綴負緯度(同上爲經度)。我唯一的問題是經度0將是0E&#xff0c;緯度0,0N。這…

oracle p l,使用P.A.L制作便携软件 (一) 基本原理 | 么么哒拥有者

因爱好自学所得&#xff0c;并非专业&#xff0c;此处只是抛砖引玉&#xff0c;欢迎相互交流、学习、提高&#xff0c;辛苦码字不易&#xff0c;如转载望保留链接出处。简单介绍&#xff1a;P.A.L是PortableApps.com Launcher的简称&#xff0c;它是PortableApps.com开发的便携…

oracle form执行后左上角没出现oracle标记,oracle form学习笔记

新增form步骤打开模板TEMPLATE&#xff0c;将其改成自己所要的名称&#xff0c;删除Data Blacks中的BLOCKNAME,DETAILBLOCK,删除Canvases中的BLOCKNAME,删除Windows中的BLOCKNAME,新增自己的Windows&#xff0c;Canvases&#xff0c;DateBlacks&#xff0c;在form级别的PRE-FOR…

linux 建oracle分区表,Oracle 10g 11g分区表创建举例

1.3. 创建其他类型分区表1.3.1. 用多列分区键创建范围分区表SQL> create table aning_mutilcol_range2 (aning_id number,3 aning_name varchar2(100),4 aning_year number,5 aning_month number,6 aning_day number,7 aning_amount number8 )9 partition by range (aning_y…

php carbon 连续日期,日期及时间处理包 Carbon 在 Laravel 中的简单使用

在编写 PHP 应用时经常需要处理日期和时间&#xff0c;这篇文章带你了解一下 Carbon – 继承自 PHP DateTime 类的 API 扩展&#xff0c;它使得处理日期和时间更加简单。Laravel 中默认使用的时间处理类就是 Carbon。namespace Carbon;class Carbon extends \DateTime{// code …

chmod g s oracle,chmod

chmod(1)名称chmod - 更改文件的权限模式用法概要chmod [-fR] absolute-mode file...chmod [-fR] symbolic-mode-list file...chmod [-fR] acl_operation file...chmod [-fR] [- named_attribute]...attribute_specification_list file...描述chmod 实用程序可更改或分配文件的…

linux lzo 压缩文件,Linux常用压缩和解压命令

.tar 解包 tar xvf filename.tar.tar 打包 tar cvf filename.tar dirname.gz 解压1 gunzip filename.gz.gz 解压2 gzip -d filename.gz.gz 压缩 gzip filename.tar.gz 和 .tgz 解压 tar zxvf filename.tar.gz.tar.gz 和 .tgz 压缩 tar zcvf filename.tar.gz dirname.bz2 解压1 …

linux进程cpu时间片,能讲一下在Linux系统中时间片是怎么分配的还有优先级的具体算法是...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼图 1 RT-Linux结构RT -Linux的关键技术是通过软件来模拟硬件的中断控制器。当Linux系统要封锁CPU的中断时时&#xff0c;RT-Linux中的实时子系统会截取到这个请求&#xff0c;把它记录下来&#xff0c;而实际上并不真正封锁硬件中断…