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. Java集合篇之深度解析Queue,单端队列、双端队列、优先级队列、阻塞队列

    写在开头 队列是Java中的一个集合接口,之前的文章已经讲解了List和Set,那么今天就来唠一唠它吧.队列的特点:存储的元素是有序的.可重复的. 队列的两大接口Queue vs Deque Queu ...

  2. MySQL表锁定处理

    研发要在一个ol_poster_sign表加字段,表比较大有400多万条,用gh-ost加字段时,在切换过程中一直报错: 无法完成最后的切换: INFO Magic cut-over table cr ...

  3. Java异常处理的20个最佳实践:告别系统崩溃

    引言 在Java编程中,异常处理是一个至关重要的环节,它不仅涉及到程序的稳定性和安全性,还关系到用户体验和系统资源的合理利用.合理的异常处理能够使得程序在面对不可预知错误时,能够优雅地恢复或者给出明确 ...

  4. Taurus.MVC WebMVC 入门开发教程3:数据绑定Model

    前言: 在这篇 Taurus.MVC WebMVC 入门开发教程的第三篇文章中, 我们将重点介绍如何进行数据绑定操作,还会学习如何使用 ${属性名称} CMS 语法来绑定页面上的元素与 Model 中 ...

  5. Elasticsearch-Mapping(映射)

    Elasticsearch-Mapping(映射) Mapping是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和 索引的. 哪些字符串属性应该被看做全文本属性(f ...

  6. 【LeetCode链表#10】删除链表中倒数第n个节点(双指针)

    删除链表倒数第N个节点 力扣题目链接(opens new window) 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. 进阶:你能尝试使用一趟扫描实现吗? 示例 1: 输入:he ...

  7. Java HashMap 详解

    HashMap HashMap 继承自 AbstractMap,实现了 Map 接口,基于哈希表实现,元素以键值对的方式存储,允许键和值为 null.因为 key 不允许重复,因此只能有一个键为 nu ...

  8. 【Azure 应用程序见解】通过无代码方式在App Service中启用Application Insights后,如何修改在Application Insights中显示的App Service实例名呢?

    问题描述 在App Service中,可以非常容易的启动Application Insights服务.默认情况中,在Application Insights中查看信息时候,其中的对象名称默认为App ...

  9. 浅入Kubernetes(4):使用Minikube体验

    Minikube 打开 https://github.com/kubernetes/minikube/releases/tag/v1.19.0 下载最新版本的二进制软件包(deb.rpm包),再使用 ...

  10. Python项目维护不了?可能是测试没到位。Django的单元测试和集成测试初探

    前言 好久没搞 Django 了,最近维护一个我之前用 Django 开发的项目竟然有亲切的感觉 测试,在以前确实是经常被忽略的话题,特别是对于 Python Web 这种快速开发框架,怎么敏捷怎么来 ...