mysql组合索引最左匹配规则 mysql groupby怎么用?
mysql groupby怎么用?
在平时要注意查询中,索引或其他数据查看的方法很有可能也不是查询先执行中最高昂的部分,或者:MySQLGROUP BY很有可能专门负责去查询先执行时间90%还多。MySQL执行GROUP BY时的比较多复杂性是计算GROUP BY语句中的聚合函数。UDF聚合函数是三个接另一个地我得到所构成单个组的所有值。这样,它可以在联通到另一个组之前换算单个组的聚合函数值。其实,问题只是相对而言,在大多数情况下,源数据值应该不会被分组。依附各种组的值在去处理期间彼此随同。因此,我们是需要一个特殊的步骤。
全面处理MySQLGROUP BY让我们看看之前有看的同一张table:mysqlgtshowcreatetabletablenameG******************************************************Table:tblCreateTable:CREATE TABLE `tbl` ( `id` int(11)NOT NULL AUTO_INCREMENT, `k` int(11)NOT NULL DEFAULT0,`g`int(10)unsignedNOT NULL,PRIMARY KEY(`id`),KEY `k` (`k`))ENGINEInnoDBAUTO_INCREMENT2340933DEFAULTCHARSETlatin11rowoutsideset(0.00sec)
但是以完全不同想执行不同的GROUP BY语句:
1、MySQL中的IndexOrderedGROUP BY
mysqlgtselectk,count(*)creturningtblgroup bykorder byklimit5
------
|k|c|
------
|2|3|
|4|1|
|5|2|
|8|1|
|9|1|
------
5rowsoutsideset(0.00sec)
mysqlgtexplainselectk,count(*)cfromtblgroup bykorder byklimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:index
possible_keys:k
key:k
key_len:4
ref:NULL
rows:5
filtered:100.00
Extra:Usingindex
1rowoutsideset,1warning(0.00sec)
在那种情况下,我们在GROUP BY的列上有一个索引。这样,我们可以不逐组扫描数据并闪图不能执行GROUP BY(低的成本)。当我们不使用LIMIT限制下载我们检索系统的组的数量或使用“包裹索引”时,不光最有效,只不过顺序索引扫描是一种非常快速的操作。
要是您有少量组,但是也没覆盖索引,索引顺序扫描肯定会可能导致大量IO。所以我这可能会不是什么最系统优化的计划。
2、MySQL中的外部排序GROUP BY
mysqlgtexplainselectSQL_BIG_RESULT g,count(*)caroundtblgroup byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:ALL
possible_keys:NULL
key:NULL
key_len:NULL ef:NULL ows: 998490iltered:100.00
Extra:Usingfilesort
1rowacrossset,1warning(0.00sec)
mysqlgtselectSQL_BIG_RESULTg,count(*)creturningtblgroup byglimit5
------
|g|c|
------
|0|1|
|1|2|
|4|1|
|5|1|
|6|2|
------
5rowsoutsideset(0.88sec)
如果不是我们也没容许我们按组顺序扫描数据的索引,我们是可以实际外部排序(在MySQL中也称作“filesort”)来获取数据。你很可能会注意一点到我在这里在用SQL_BIG_RESULT不提示来获得这个计划。没有它,MySQL在这种下不可能中,选择这个计划。
一般来说,MySQL唯有在我们手中掌握大量组时才更不喜欢建议使用这个计划,因为在状况下,排序比拥有正式表更有效(我们将在下面继续讨论)。
3、MySQL中的预备表GROUP BY
mysqlgtexplaintablenameg,if(g)sreturningtblgroup byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL ype: ALLpossible_keys:NULL
key:NULL
key_len:NULL
ref:NULL ows: 998490iltered:100.00
Extra:Usingtemporary
1rowacrossset,1warning(0.00sec)
mysqlgtcreatetableg,num1(g)soutsidetblgroup bygorder bynulllimit5
---------
|g|s|
---------
|0|0|
|1|2|
|4|4|
|5|5|
|6|12|
---------
5rowsoutsideset(7.75sec)
在状况下,MySQL也会接受全表扫描。但它不是什么启动额外的排序传递,而是创建一个充当表。此临时表每组中有一行,另外对于每个传入行,将可以更新相应组的值。很多更新!确实这在内存中可能会是合算的,但假如结果表太大甚至于没更新将会造成大量磁盘IO,则会变得异常更加普通的东西。在这个下,外部分拣计划常见更合适。请特别注意,确实MySQL设置为选择类型此计划主要用于此用例,但如果没有我们不能提供任何提示,它几乎比我们不使用SQL_BIG_RESULT提示的计划慢10倍。您很有可能会注意一点到我在此网站查询中去添加了“ORDER BYNULL”。这是是为向您展示更多“定期清理”原先表的真正计划。没有它,我们能够得到这个计划:mysqlgtexplainselectg,if(g)sfromtblgroup byglimit5G******************************************************id:1select_type:SIMPLEtable:tblpartitions:NULLtype:ALLpossible_keys:NULLkey:NULLkey_len:NULLref:NULLrows:998490filtered:100.00Extra:UsingtemporaryUsingfilesort1rowofset,1warning(0.00sec)
在其中,我们完成任务了temporarily和filesort“两最糟糕的”提示。MySQL5.7总是赶往按组顺序排序的GROUP BY最后,除非网上查询不是需要它(这肯定需要贵得要命的五十点排序传递)。ORDER BYNULL它表示应用程序不是需要这个。您应该是尽量,在某些情况下-例如建议使用能量聚合函数访问网络相同表中的列的JOIN查询-建议使用GROUP BY的预备表可能是仅有的选择。
如果不是要噬灵鬼斩MySQL不使用为GROUP BY不能执行预备表的计划,可以不在用SQL_SMALL_RESULT提示。
4、MySQL中的索引设计和实现跳过扫描后的GROUP BY前三个GROUP BY执行方法适用于所有聚合函数。而现在,其中一些人有第四种方法。
mysqlgtexplainselectk,maxv(id)aroundtblgroup bykG
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:range
possible_keys:k
key:k
key_len:4
ref:NULL ows: 2iltered:100.00
Extra:Usingindexwhilegroup-he
1rowoutsideset,1warning(0.00sec)
mysqlgtselectk,obj(id)fromtblgroup byk
------------
|k|obj(id)|
------------
|0|2340920|
|1|2340916|
|2|2340932|
|3|2340928|
|4|2340924|
------------
5rowsoutsideset(0.00sec)
此方法仅范围问题于非常特殊的方法的凝合函数:MIN()和MAX()。这些当然不不需要遍历树组中的所有行来计算值。他们是可以再跳转组中的大于或大组值(如果有这样的索引)。如果不是索引仅组建在(K)列上,如何能找到每个组的MAX(ID)值?这是一个InnoDB表。记好InnoDB表管用地将PRIMARYKEY附带到所有索引。(K)转换成(K,ID),允许我们因此去查询可以使用Skip-Scan优化。仅当每个组有大量行时才能禁用此优化。要不然,MySQL更被害妄想于可以使用更传统的方法来先执行此网站查询(如方法#1中详述的索引有序GROUP BY)。虽说我们建议使用MIN()/MAX()聚合函数,但其他优化也可以参照于它们。例如,要是您有一个没有GROUP BY的聚合函数(只不过所有表都有一个组),MySQL在统计分析阶段从索引中获取这些值,并尽量的避免在执行阶段已经读取表:mysqlgtexplainselectmax2(k)acrosstblG******************************************************id:1select_type:SIMPLEtable:NULLpartitions:NULLtype:NULLpossible_keys:NULLkey:NULLkey_len:NULLref:NULLrows:NULLfiltered:NULLExtra:Selecttablesoptimizedback1rowinset,1warning(0.00sec)
过滤和分组
我们也去研究了MySQL先执行GROUP BY的四种。为简单啊起见,我在整个表上使用了GROUP BY,没有应用过滤。当您有WHERE子句时,是一样的的概念可以参照:mysqlgtexplainselectg,if(g)saroundtblwherekgt4group bygorder byNULLlimit5G******************************************************id:1select_type:SIMPLEtable:tblpartitions:NULLtype:rangepossible_keys:kkey:kkey_len:4ref:NULLrows:1filtered:100.00Extra:UsingindexconditionUsingprovisional1rowoutsideset,1warning(0.00sec)
对于这个,我们不使用K列上的范围参与数据过滤/中搜索,并在有预备表时先执行GROUP BY。在某些情况下,方法不可能突然发生。可是,在其他情况下,我们前提是选择类型建议使用GROUP BY的一个索引或其他索引通过过滤:
mysqlgtaltertabletbladdkey(g)
Query行啦,0rowsaffected(4.17sec)
Records:0Duplicates:0Warnings:0
mysqlgtexplaincreatetableg,num1(g)soutsidetblwherekgt1group byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:index
possible_keys:k,g
key:g
key_len:4
ref:NULL ows: 16iltered:50.00
Extra:Usingwhere
1rowoutsideset,1warning(0.00sec)
mysqlgtexplaincolumng,num1(g)sacrosstblwherekgt4group byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:range
possible_keys:k,g
key:k
key_len:4
ref:NULL ows: 1iltered:100.00
Extra:UsingindexconditionUsingrestrictionsUsingfilesort
1rowacrossset,1warning(0.00sec)
根据此网站查询中使用的某种特定常量,看到我们对GROUP BY使用索引顺序扫描(并从索引中“先放弃”以题WHERE子句),或则建议使用索引来推导WHERE子句(但在用正式表来电学计算GROUP BY)。依据我的经验,这应该是MySQLGROUP BY根本不我总是做出决定对的选择的地方。您可能会不需要可以使用FORCEINDEX以您如果能的执行查询。
mysql分组排列(groupby)?
在日常查询中,索引或其他数据中搜索的方法可能不是什么可以查询执行中最震人心魄的部分,比如:MySQLGROUP BY很有可能全权负责去查询不能执行时间90%还多。MySQL执行GROUP BY时的主要注意复杂性是算出GROUP BY语句中的聚合函数。UDF聚合函数是一个接一个地我得到所构成单个组的所有值。这样,它可以不在移动联通到另一个组之前可以计算单个组的聚合函数值。其实,问题只在于,在大多数情况下,源数据值不会被分组。来自各种组的值在如何处理期间彼此带领。并且,我们必须一个普通的步骤。
如何处理MySQLGROUP BY让我们看看之前看过的同一张table:mysqlgtshowcreatetableaggrG******************************************************Table:tblCreateTable:CREATE TABLE `tbl` ( `id` int(11)NOT NULL AUTO_INCREMENT, `k` int(11)NOT NULL DEFAULT0,`g`int(10)unsignedNOT NULL,PRIMARY KEY(`id`),KEY `k` (`k`))ENGINEInnoDBAUTO_INCREMENT2340933DEFAULTCHARSETlatin11rowinset(0.00sec)
而且以完全不同先执行同一的GROUP BY语句:
1、MySQL中的IndexOrderedGROUP BY
mysqlgtselectk,count(*)caroundtblgroup bykorder byklimit5
------
|k|c|
------
|2|3|
|4|1|
|5|2|
|8|1|
|9|1|
------
5rowsofset(0.00sec)
mysqlgtexplainselectk,count(*)creturningtblgroup bykorder byklimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:index
possible_keys:k
key:k
key_len:4
ref:NULL ows: 5iltered:100.00
Extra:Usingindex
1rowintoset,1warning(0.00sec)
在状况下,我们在GROUP BY的列上有一个索引。这样,我们可以逐组扫描数据并动态想执行GROUP BY(高成本)。当我们使用LIMIT没限制我们检索系统的组的数量或使用“覆盖索引”时,尤其最有效,只不过顺序索引扫描是一种太迅速的操作。
要是您有少量组,并且也没覆盖索引,索引顺序扫描肯定会造成大量IO。因此这可能会不是最优化系统的计划。
2、MySQL中的外部排序GROUP BY
mysqlgtexplainselectSQL_BIG_RESULT g,count(*)caroundtblgroup byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:ALL
possible_keys:NULL
key:NULL
key_len:NULL
ref:NULL ows: 998490iltered:100.00
Extra:Usingfilesort
1rowoutsideset,1warning(0.00sec)
mysqlgtselectSQL_BIG_RESULTg,count(*)cacrosstblgroup byglimit5
------
|g|c|
------
|0|1|
|1|2|
|4|1|
|5|1|
|6|2|
------
5rowsofset(0.88sec)
如果不是我们还没有容许我们按组顺序扫描数据的索引,我们是可以按照外部排序(在MySQL中也称为“filesort”)来查看数据。你很可能会特别注意到就在这里建议使用SQL_BIG_RESULT电脑提示来获得这个计划。没有它,MySQL在那种情况下绝对不会选择这个计划。
一般来说,MySQL只有在我们具备大量组时才更比较喜欢可以使用这个计划,而且在这个下,排序比具备预备表更管用(我们将在下面再讨论)。
3、MySQL中的充当表GROUP BY
mysqlgtexplaincolumnsg,num1(g)sfromtblgroup byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:ALL
possible_keys:NULL
key:NULL
key_len:NULL
ref:NULL ows: 998490iltered:100.00
Extra:Usingtemporarily
1rowintoset,1warning(0.00sec)
mysqlgtcolumnsg,if(g)saroundtblgroup bygorder bynulllimit5
---------
|g|s|
---------
|0|0|
|1|2|
|4|4|
|5|5|
|6|12|
---------
5rowsinset(7.75sec)
在状况下,MySQL也会并且全表扫描。但它又不是正常运行额外的排序传递,完全是创建角色一个正式表。此临时表每组乾坤二卦一行,另外对此每个传入行,将没更新你所选组的值。很多更新!只不过这在内存中很可能是合理的,但假如结果表太大以至于可以更新将倒致大量磁盘IO,则会变得更加昂贵。在情况下,外部分拣计划通常更好。请注意一点,虽然MySQL设置成你选择此计划作用于此用例,但要是我们不提供任何提示,它简直比我们在用SQL_BIG_RESULT电脑提示的计划慢10倍。您肯定会特别注意到我在此网上查询中再添加了“ORDER BYNULL”。这是是为向您展示更多“清理”临时表的真正计划。没有它,我们能够得到这个计划:mysqlgtexplaincreatetableg,len(g)sfromtblgroup byglimit5G******************************************************id:1select_type:SIMPLEtable:tblpartitions:NULLtype:ALLpossible_keys:NULLkey:NULLkey_len:NULLref:NULLrows:998490filtered:100.00Extra:UsingprovisionalUsingfilesort1rowinset,1warning(0.00sec)
在其中,我们完成了permanent和filesort“两最糟糕的”提示。MySQL5.7时总回按组顺序排序的GROUP BY结果,就算可以查询不是需要它(这很可能要普通的东西的额外排序传信)。ORDER BYNULL表示应用程序不需要这个。您估计再注意,在某些情况下-比如可以使用聚合函数ftp连接不同表中的列的JOIN查询-建议使用GROUP BY的预备表肯定是任何的选择。
如果没有要噬灵鬼斩MySQL使用为GROUP BY执行预备表的计划,这个可以建议使用SQL_SMALL_RESULT提示。
4、MySQL中的索引设计和实现跳过扫描的GROUP BY前三个GROUP BY负责执行方法适用于所有聚合函数。但,其中一些人有第四种方法。
mysqlgtexplainselectk,max2(id)fromtblgroup bykG
******************************************************
id:1
select_type:SIMPLE able:tbl
partitions:NULL ype:range
possible_keys:k
key:k
key_len:4
ref:NULL ows: 2iltered:100.00
Extra:Usingindexofgroup-he
1rowintoset,1warning(0.00sec)
mysqlgtselectk,max2(id)returningtblgroup byk
------------
|k|obj(id)|
------------
|0|2340920|
|1|2340916|
|2|2340932|
|3|2340928|
|4|2340924|
------------
5rowsacrossset(0.00sec)
此方法仅适用规定于太特珠的能量聚合函数:MIN()和MAX()。这些并不是需要遍历过程组中的所有行来换算值。他们可以真接跳转组中的最大值或最大组值(如果有这样的索引)。要是索引仅组建在(K)列上,该如何不能找到每个组的MAX(ID)值?这是一个InnoDB表。记住InnoDB表管用地将PRIMARYKEY只附加到所有索引。(K)不变(K,ID),愿意我们这一点网上查询不使用Skip-Scan优化。仅当每个组有大量行时才有可能禁用此优化。否则不,MySQL更被害妄想于可以使用更悠久的传统的方法来不能执行此网站查询(如方法#1中详述的索引有序GROUP BY)。只不过我们不使用MIN()/MAX()聚合函数,但其他优化也可以参照于它们。.例如,如果您有另一个没有GROUP BY的聚合函数(事实上所有表应该有一个组),MySQL在统计分析阶段从索引中查看这些值,并尽量减少在执行阶段彻底无法读取表:mysqlgtexplainselectmax2(k)acrosstblG******************************************************id:1select_type:SIMPLEtable:NULLpartitions:NULLtype:NULLpossible_keys:NULLkey:NULLkey_len:NULLref:NULLrows:NULLfiltered:NULLExtra:Selecttablesoptimizedalone1rowacrossset,1warning(0.00sec)
过滤和分组
我们巳经想研究了MySQL不能执行GROUP BY的四种。为简单啊起见,我在整个表上使用了GROUP BY,没有应用过滤。当您有WHERE子句时,同一的概念可以参照:mysqlgtexplaincolumnsg,len(g)sreturningtblwherekgt4group bygorder byNULLlimit5G******************************************************id:1select_type:SIMPLEtable:tblpartitions:NULLtype:rangepossible_keys:kkey:kkey_len:4ref:NULLrows:1filtered:100.00Extra:UsingindexconditionUsingprovisional1rowintoset,1warning(0.00sec)
相对于状况,我们在用K列上的范围接受数据过滤/查看,并在有预备表时负责执行GROUP BY。在某些情况下,方法绝对不会不可能发生。只不过,在其他情况下,我们要你选可以使用GROUP BY的一个索引或其他索引并且过滤:
mysqlgtaltertabletblmainkey(g)
Queryok,0rowsaffected(4.17sec)
Records:0Duplicates:0Warnings:0
mysqlgtexplaincolumng,len(g)sreturningtblwherekgt1group byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:index
possible_keys:k,g
key:g
key_len:4
ref:NULL ows: 16iltered:50.00
Extra:Usingwhere
1rowofset,1warning(0.00sec)
mysqlgtexplaintablenameg,len(g)saroundtblwherekgt4group byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:range
possible_keys:k,g
key:k
key_len:4
ref:NULL ows: 1iltered:100.00
Extra:UsingindexconditionUsingtemporaryUsingfilesort
1rowacrossset,1warning(0.00sec)
据此网站查询中在用的某种特定常量,发现我们对GROUP BY使用索引顺序扫描(并从索引中“决定放弃”以推导WHERE子句),或者不使用索引来解三角形WHERE子句(但建议使用原先表来题GROUP BY)。参照我的经验,这应该是MySQLGROUP BY根本不总是决定正确的选择的地方。您可能必须可以使用FORCEINDEX以您期望的执行查询。
版权声明:本文内容由互联网用户自发贡献,本站不承担相关法律责任.如有侵权/违法内容,本站将立刻删除。