1、group by 分组语句

在SQL中group by主要用来进行分组统计,分组字段放在group by的后面;分组结果一般需要借助聚合函数实现。

group by语法结构 1、常用语法

语法结构 SELECT column_name1,column_name2, … 聚合函数1,聚合函数2 , … FROM table_name GROUP BY column_name1,column_name2, … 说明:1、group by中的分组字段和select后的字段要保持一致;2、通常group by和聚合函数一起使用,但也可以不包含聚合函数,根据业务需求决定;3、常用的聚合函数有max()、min()、avg()、sum()、count()等。

2、影响group by的内存参数

work_mem:因为group by 语句很会用到sort、hash中的任何一中方式,如果work_mem 配置不合适就是用到temp file 进行排序,调整work_mem的目的是使相关操作尽可能在内存中执行

max_parallel_workers:并行相关参数可以条并行扫描相关的速度,是通过消耗cpu资源提升查询效率得一种方法

max_parallel_workers_per_gather:同上

3、聚合方式对group 的影响(重点介绍)

金仓数据库中针对group by 函数有两种聚合方式hashagg、groupagg

HashAggregate

对于hash聚合来说,数据库会根据group by字段后面的值算出hash值,并根据前面使用的聚合函数在内存中维护对应的列表。如果select后面有两个聚合函数,那么在内存中就会维护两个对应的数据。同样的,有n个聚合函数就会维护n个同样的数组。对于hash算法来说,数组的长度肯定是大于group by的字段的distinct值的个数的,且跟这个值应该呈线性关系,group by后面的值越唯一,使用的内存也就越大。

执行计划示例:

  1. aligputf8=# explain select count(1) from pg_class group by oid;
  2. QUERY PLAN
  3. ----------------------------------------------------------------------
  4. HashAggregate  (cost=1721.40..2020.28 rows=23910 width=4)
  5. Group By: oid
  6. ->  Seq Scan on pg_class  (cost=0.00..1004.10 rows=143460 width=4)
  7. Settings:  enable_seqscan=on
  8. (4 rows)

GroupAggregate

对于普通聚合函数,使用group聚合,其原理是先将表中的数据按照group by的字段排序,这样子同一个group by的值就在一起,这样就只需要对排好序的数据进行一次全扫描,就可以得到聚合的结果了。

执行计划示例:

  1. aligputf8=# set enable_hashagg = off;
  2. SET
  3. aligputf8=#  explain select count(1) from pg_class group by oid;
  4. QUERY PLAN
  5. ----------------------------------------------------------------------------
  6. GroupAggregate  (cost=13291.66..14666.48 rows=23910 width=4)
  7. Group By: oid
  8. ->  Sort  (cost=13291.66..13650.31 rows=143460 width=4)
  9. Sort Key: oid
  10. ->  Seq Scan on pg_class  (cost=0.00..1004.10 rows=143460 width=4)
  11. Settings:  enable_hashagg=off; enable_seqscan=on
  12. (6 rows)

在不考虑聚合函数的前提下,从上面的两个执行计划的cost来说,GroupAgg 由于需要排序,效率很差,消耗是HashAggregate的7倍。

但是HashAgg也不是万能的,从定义中可以看到在select 查询中用到一个聚合函数hashagg就需要额外维护一个数组。如果的情况下hashagg效率会随着聚合函数的增加直线上升。

对比两种聚合方式

  • hashagg 不进行排序操作,所以如果对结果集顺序不做要求的情况下有限hashagg

  • hashagg 的资源消耗会随着聚合函数的增加直线上升。

实验数据

1、构造1000万行测试数据

create table t1(id int primary key, a int, b int);

declare

i int;

begin

i=1;

while(i<=10000000) loop

insert into t1 values(i, i, i);

i=i+1;

end loop;

end;

测试场景一:不带聚合函数

HashAggregate聚合

kingbase=# explain (analyze true ,buffers true) SELECT /*+hashagg*/  a%10 as m,b%100 n  from t1 group by m ,n;

QUERY PLAN
HashAggregate  (cost=254348.64..404349.12 rows=10000032 width=8) (actual time=4264.745..4317.458 rows=100 loops=1)
Group Key: (a % 10), (b % 100)
Buffers: shared hit=10948 read=43400
->  Seq Scan on t1  (cost=0.00..204348.48 rows=10000032 width=8) (actual time=0.098..2026.376 rows=10000000 loops=1)
Buffers: shared hit=10948 read=43400
Planning Time: 0.059 ms
Execution Time: 4524.736 ms
(7 rows)

GroupAggregate聚合

kingbase=# explain (analyze true ,buffers true) SELECT   a%10 as m,b%100 n  from t1 group by m ,n;

QUERY PLAN
Group  (cost=1367027.26..1492027.66 rows=10000032 width=8) (actual time=8414.506..12554.006 rows=100 loops=1)
Group Key: ((a % 10)), ((b % 100))
Buffers: shared hit=11015 read=43336
->  Sort  (cost=1367027.26..1392027.34 rows=10000032 width=8) (actual time=8414.498..11298.553 rows=10000000 loops=1)
Sort Key: ((a % 10)), ((b % 100))
Sort Method: quicksort  Memory: 861967kB
Buffers: shared hit=11015 read=43336
->  Seq Scan on t1  (cost=0.00..204348.48 rows=10000032 width=8) (actual time=0.030..2049.870 rows=10000000 loops=1)
Buffers: shared hit=11012 read=43336
Planning Time: 0.060 ms
Execution Time: 12606.549 ms
(11 rows)

针对1000万数据在没有聚合函数情况下 hashagg性能是groupagg的两倍以上

测试场景二:少量聚合函数

HashAggregate聚合

kingbase=#explain (analyze true,buffers true) SELECT /+hashagg/ a%10 as m,b%100 n ,max(a),max(b),avg(a),avg(b) from t1 group by m ,n;

QUERY PLAN
HashAggregate  (cost=10000354348.96..10000554349.60 rows=10000032 width=80) (actual time=5248.529..5308.127 rows=100 loops=1)
Group Key: (a % 10), (b % 100)
Buffers: shared hit=11076 read=43272
->  Seq Scan on t1  (cost=0.00..204348.48 rows=10000032 width=16) (actual time=0.055..2152.745 rows=10000000 loops=1)
Buffers: shared hit=11076 read=43272
Planning Time: 0.188 ms
Execution Time: 5541.141 ms
(7 rows)

GroupAggregate聚合

kingbase=# explain (analyze true ,buffers true) SELECT   a%10 as m,b%100 n ,max(a),max(b),avg(a),avg(b) from t1 group by m ,n;

QUERY PLAN
GroupAggregate  (cost=1367027.26..1742028.46 rows=10000032 width=80) (actual time=9070.775..14161.918 rows=100 loops=1)
Group Key: ((a % 10)), ((b % 100))
Buffers: shared hit=11044 read=43304
->  Sort  (cost=1367027.26..1392027.34 rows=10000032 width=16) (actual time=9010.429..11943.928 rows=10000000 loops=1)
Sort Key: ((a % 10)), ((b % 100))
Sort Method: quicksort  Memory: 861967kB
Buffers: shared hit=11044 read=43304
->  Seq Scan on t1  (cost=0.00..204348.48 rows=10000032 width=16) (actual time=0.017..2160.858 rows=10000000 loops=1)
Buffers: shared hit=11044 read=43304
Planning Time: 0.118 ms
Execution Time: 14221.171 ms
(11 rows)

测试场景三:大量聚合函数

HashAggregate聚合

explain(analyze true,buffers true)
SELECT/*+hashagg*/a%10 as m,b%100 n ,max(a),max(b),avg(a),avg(b),min(a),min(b),sum(a),sum(b),sum(a+b),sum(a-b) from t1 group by m ,n;
QUERY PLAN
HashAggregate  (cost=10000554349.60..10000754350.24 rows=10000032 width=120) (actual time=6070.836..6131.290 rows=100 loops=1)
Group Key: (a % 10), (b % 100)
Buffers: shared hit=11204 read=43144
->  Seq Scan on t1  (cost=0.00..204348.48 rows=10000032 width=16) (actual time=0.096..2148.660 rows=10000000 loops=1)
Buffers: shared hit=11204 read=43144
Planning Time: 0.138 ms
Execution Time: 6359.172 ms
(7 rows)

本次只是大量聚合函数测试可以看到HashAggregate 相较于场景二时间变长1s中左右, 具体多少聚合函数会对hashagg 有比较大的影响还需要大家深入探讨

测试场景四:hashagg 走索引

总结

可以看出,对于GroupAgg来说,消耗的内存基本上是恒定的,无论group by哪个字段。当聚合函数较少的时候,速度也相对较慢,但是相对稳定。

HashAgg在少数聚合函数是表现优异,但是很多聚合函数,性能跟消耗的内存差异很明显。尤其是受group by字段的唯一性很明显,字段count(district)值越大,hash聚合消耗的内存越多,性能下降剧烈。

所以在sql中有大量聚合函数,group by 的字段由相对比较唯一的时候,应该用GroupAgg,而不能用HashAgg。

kingbase ES group by 语句优化的更多相关文章

  1. group by 语句怎么优化?

    一.一个简单使用示例 我这里创建一张订单表 CREATE TABLE `order_info` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `or ...

  2. SQL语句优化

    (1)      选择最有效率的表名顺序 ( 只在基于规则的优化器中有效 ) : ORACLE 的解析器按照从右到左的顺序处理 FROM 子句中的表名, FROM 子句中写在最后的表 ( 基础表dri ...

  3. sql语句优化SQL Server

    MS   SQL   Server查询优化方法查询速度慢的原因很多,常见如下几种 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)          2.I/O吞吐量小,形成了 ...

  4. 优化数据库的方法及SQL语句优化的原则

    优化数据库的方法: 1.关键字段建立索引. 2.使用存储过程,它使SQL变得更加灵活和高效. 3.备份数据库和清除垃圾数据. 4.SQL语句语法的优化.(可以用Sybase的SQL Expert,可惜 ...

  5. 数据库性能调优——sql语句优化(转载及整理) —— 篇2

    下面是在网上搜集的一些个人认为比较正确的调优方案,如有错误望指出,定虚心改正 (1) 选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE 的解析器按照从右到左的顺序处理FROM子句中 ...

  6. 数据库性能优化之SQL语句优化

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的编写等是体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统 ...

  7. MYSQL查询语句优化

    mysql的性能优化包罗甚广: 索引优化,查询优化,查询缓存,服务器设置优化,操作系统和硬件优化,应用层面优化(web服务器,缓存)等等.这里的记录的优化技巧更适用于开发人员,都是从网络上收集和自己整 ...

  8. oracle学习 十 数据库的语句优化(持续更)

    平时关注Oracle数据库的网友都知道,Oracle性能优化保证了Oracle数据库的健壮性.下面就此提出需要注意的两个原则.   原则一:注意WHERE子句中的连接顺序: ORACLE采用自下而上的 ...

  9. 浅谈SQL语句优化经验

    (1) 选择最有效率的表名顺序(只在基于规则的seo/' target='_blank'>优化器中有效):ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后 ...

  10. 整理:sql语句优化之SQL Server

    . 增加服务器CPU个数;但是必须明白并行处理串行处理更需要资源例如内存.使用并行还是串行程是MsSQL自动评估选择的.单个任务分解成多个任务,就可 以在处理器上运行.例如耽搁查询的排序.连接.扫描和 ...

随机推荐

  1. useMemo与useCallback

    useMemo与useCallback useMemo和useCallback都可缓存函数的引用或值,从更细的角度来说useMemo则返回一个缓存的值,useCallback是返回一个缓存函数的引用. ...

  2. oracle中约束(constraints)是如何影响查询计划的

    原文: http://www.oracle.com/technetwork/issue-archive/2009/09-may/o39asktom-096149.html oracle中约束(cons ...

  3. 解决SQLyog连接mysql报错:Your password has expired

    解决步骤如下: D:\program\mysql-5.7.16-winx64\bin>mysql -uroot -p Enter password: ******* Welcome to the ...

  4. win32 - 在cmd中禁用进程权限

    C:\Users\path>whoami /priv 在cmd中输入whoami /priv后将获得当前令牌(标准用户)的权限. C:\Users\path>tasklist /v /fo ...

  5. ASP.NET 通过拦截器记录错误日志

    前言 主要是记录一下实现的错误日志拦截,可以在拦截器里面控制返回的信息,把错误信息处理后返回给请求端. 代码实战 拦截器 /// <summary> /// 接口异常捕捉过滤器 /// & ...

  6. 第136篇:动画API:setInterval 与 requestAnimationFrame的区别

    好家伙,书接上文   function animate() { //请求-动画-框架 requestAnimationFrame( animate ); //改变正方体在场景中的位置,让正方体动起来 ...

  7. 【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题

    问题描述 启用App Service Local Git 部署,在Clone 代码库到本地时候,卡在Clone 'xxxxxx' ... ... 一动不动的问题? 问题解答 因为Git Clone没有 ...

  8. 【Azure Redis 缓存 Azure Cache For Redis】Redis支持的版本及不同版本迁移风险

    问题描述 1. Azure Redis缓存支持的版本包括4.0以及6.0(预览) 这种情形下,可以使用PaaS服务提供的 Azure Redis 缓存(4.0版本).Azure Redis对6.0的支 ...

  9. adb monkey 有哪些参数?

    adb monkey 是 Android Debug Bridge (ADB) 工具中的一个命令,用于执行随机事件来对 Android 应用进行压力测试.以下是 adb monkey 命令的一些常用参 ...

  10. Java 对属性赋值的位置 执行的先后顺序

    1 package com.bytezreo.block; 2 3 /** 4 * 5 * @Description 对属性赋值的位置: 6 * @author Bytezero·zhenglei! ...