PostgrSQL 递归SQL的几个应用 - 极客与正常人的思维

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介:

标签

PostgreSQL , with recursive , 递归查询 , 求差 , 求唯一值 , 求稀疏列 , 求时序数据最新值


背景

递归SQL的几个应用

递归查询,在几个场景的应用,有十全大补丸的功效。

一、求唯一值

场景

某张表,数据量在亿级别,求某稀疏列的唯一值。

create table sex (sex char(1), otherinfo text);    
create index idx_sex_1 on sex(sex);    
insert into sex select 'm', generate_series(1,50000000)||'this is test';    
insert into sex select 'w', generate_series(1,50000000)||'this is test';    

正常人的做法 - 蜗牛

select distinct col from table ;  

蜗牛般的速度。

极客的做法 - 0.17毫秒

with recursive skip as (    
  (    
    select min(t.sex) as sex from sex t where t.sex is not null    
  )    
  union all    
  (    
    select (select min(t.sex) as sex from sex t where t.sex > s.sex and t.sex is not null)     
      from skip s where s.sex is not null   
  )    
)     
select * from skip where sex is not null;   
  
Total runtime: 0.173 ms    

飞一般的感觉。

二、求差

场景

一张小表A,里面存储了一些ID,大约几百个。

(比如说巡逻车辆ID,环卫车辆的ID,公交车,微公交的ID)。

另外有一张日志表B,每条记录中的ID是来自前面那张小表的,但不是每个ID都出现在这张日志表中,比如说一天可能只有几十个ID会出现在这个日志表的当天的数据中。

(比如车辆的行车轨迹数据,每秒上报轨迹,数据量就非常庞大)。

怎么快速的找出今天没有出现的ID?

(哪些巡逻车辆没有出现在这个片区,是不是偷懒了?哪些环卫车辆没有出行,哪些公交或微公交没有出行)?

建表

create table a(id int primary key, info text);  
  
create table b(id int primary key, aid int, crt_time timestamp);  
create index b_aid on b(aid);  

插入测试数据

-- a表插入1000条  
insert into a select generate_series(1,1000), md5(random()::text);  
  
-- b表插入500万条,只包含aid的500个id。  
insert into b select generate_series(1,5000000), generate_series(1,500), clock_timestamp();  

正常人的做法 - 2.3秒

select * from a where id not in (select aid from b);   
618秒  
  
select a.id from a left join b on (a.id=b.aid) where b.* is null;  
2.3秒  

极客的做法 - 11毫秒

select * from a where id not in   
(  
with recursive skip as (    
  (    
    select min(aid) aid from b where aid is not null    
  )    
  union all    
  (    
    select (select min(aid) aid from b where b.aid > s.aid and b.aid is not null)     
      from skip s where s.aid is not null    
  )    
)     
select aid from skip where aid is not null  
);  
  
11毫秒  

飞一般的感觉。

三、求时序数据最新值

场景

有很多传感器,不断的在上报数据,用户需要查询当前最新的,每个传感器上报的值。

这种需求,可以使用窗口查询,但是如何加速,如何快速的取出批量数据?

创建测试表如下,

create unlogged table sort_test(  
  id serial8 primary key,  -- 主键  
  c2 int,  -- 传感器ID  
  c3 int  -- 传感器值  
);    

写入1000万传感器测试数据,10万个传感器。

postgres=# insert into sort_test (c2,c3) select random()*100000, random()*100 from generate_series(1,10000000);  
INSERT 0 10000000  

正常人的做法 - 44秒

select id,c2,c3 from (select id,c2,c3,row_number() over(partition by c2 order by id desc) rn from sort_test) t where rn=1;  
  
44秒  

极客的做法 - 4秒

postgres=# create index sort_test_1 on sort_test(c2,id desc);   
CREATE INDEX  
  
with recursive skip as (    
  (    
    select (c2,c3)::r as r from sort_test where id in (select id from sort_test where c2 is not null order by c2,id desc limit 1)   
  )    
  union all    
  (    
    select (  
      select (c2,c3)::r as r from sort_test where id in (select id from sort_test t where t.c2>(s.r).c2 and t.c2 is not null order by c2,id desc limit 1)   
    ) from skip s where (s.r).c2 is not null  
  )      
)     
select (t.r).c2, (t.r).c3 from skip t where t.* is not null;   
  
4.2秒  

如果数据需要处理或实时展示,流式返回

postgres=# begin;  
BEGIN  
Time: 0.079 ms  
postgres=# declare cur cursor for with recursive skip as (    
  (    
    select (c2,c3)::r as r from sort_test where id in (select id from sort_test where c2 is not null order by c2,id desc limit 1)   
  )    
  union all    
  (    
    select (  
      select (c2,c3)::r as r from sort_test where id in (select id from sort_test t where t.c2>(s.r).c2 and t.c2 is not null order by c2,id desc limit 1)   
    ) from skip s where (s.r).c2 is not null  
  )      
)     
select (t.r).c2, (t.r).c3 from skip t where t.* is not null;   
DECLARE CURSOR  
Time: 1.240 ms  
postgres=# fetch 100 from cur;  
    r       
----------  
 (0,93)  
 (1,52)  
 (2,65)  
.....  
  (97,78)  
 (98,44)  
 (99,99)  
(100 rows)  
  
Time: 4.314 ms  

飞一般的感觉。

原理

通过递归,结合索引,收敛需要扫描的数据块,极大的减少IO,CPU开销。同时在时序场景,减少SORT和GROUP的开销。

pic

递归的其他应用

《PostgreSQL 递归查询CASE - 树型路径分组输出》

《用PostgreSQL找回618秒逝去的青春 - 递归收敛优化》

《distinct xx和count(distinct xx)的变态递归优化方法 - 索引收敛(skip scan)扫描》

《时序数据合并场景加速分析和实现 - 复合索引,窗口分组查询加速,变态递归加速》

《PostgreSQL 使用递归SQL 找出数据库对象之间的依赖关系》

《PostgreSQL 递归死循环案例及解法》

《PostgreSQL 递归查询一例 - 资金累加链》

《PostgreSQL Oracle 兼容性之 - WITH 递归 ( connect by )》

《递归优化CASE - group by & distinct tuning case : use WITH RECURSIVE and min() function》

《递归优化CASE - performance tuning case :use cursor\trigger\recursive replace (group by and order by) REDUCE needed blockes scan》

《PostgreSQL 树状数据存储与查询(非递归) - Use ltree extension deal tree-like data type》

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
SQL 存储 测试技术
SQL在构建系统中的应用:关键步骤与技巧
在构建基于数据库的应用系统时,SQL(Structured Query Language)作为与数据库交互的核心语言,扮演着至关重要的角色
|
9月前
|
SQL Oracle 关系型数据库
解决大小写、保留字与特殊字符问题!Oracle双引号在SQL中的特殊应用
在Oracle数据库开发中,双引号的使用是一个重要但易被忽视的细节。本文全面解析了双引号在SQL中的特殊应用场景,包括解决标识符与保留字冲突、强制保留大小写、支持特殊字符和数字开头标识符等。同时提供了最佳实践建议,帮助开发者规避常见错误,提高代码可维护性和效率。
379 6
|
SQL 数据库
如何应用SQL约束条件?
【10月更文挑战第28天】如何应用SQL约束条件?
379 11
|
SQL Oracle 关系型数据库
SQL语言的主要标准及其应用技巧
SQL(Structured Query Language)是数据库领域的标准语言,广泛应用于各种数据库管理系统(DBMS)中,如MySQL、Oracle、SQL Server等
472 9
|
SQL 数据库 数据库管理
数据库SQL函数应用技巧与方法
在数据库管理中,SQL函数是处理和分析数据的强大工具
|
SQL 存储 数据库
SQL在构建系统中的应用:关键要素与编写技巧
在构建基于数据库的系统时,SQL(Structured Query Language)扮演着至关重要的角色
|
SQL 关系型数据库 数据库
SQL数据库:核心原理与应用实践
随着信息技术的飞速发展,数据库管理系统已成为各类组织和企业中不可或缺的核心组件。在众多数据库管理系统中,SQL(结构化查询语言)数据库以其强大的数据管理能力和灵活性,广泛应用于各类业务场景。本文将深入探讨SQL数据库的基本原理、核心特性以及实际应用。一、SQL数据库概述SQL数据库是一种关系型数据库
485 5
|
SQL 存储 Oracle
Oracle数据库SQL语句详解与应用指南
在数字化时代,数据库已成为各类企业和组织不可或缺的核心组件。Oracle数据库作为业界领先的数据库管理系统之一,广泛应用于各种业务场景。掌握Oracle数据库的SQL语句是数据库管理员、开发人员及运维人员的基本技能。本文将详细介绍Oracle数据库SQL语句的基本概念、语法、应用及最佳实践。一、Or
568 3
|
SQL
sql树型应用总结
sql树型应用总结
110 2
|
SQL 监控 安全
员工上网行为监控软件:SQL 在数据查询监控中的应用解析
在数字化办公环境中,员工上网行为监控软件对企业网络安全和管理至关重要。通过 SQL 查询和分析数据库中的数据,企业可以精准了解员工的上网行为,包括基础查询、复杂条件查询、数据统计与分析等,从而提高网络管理和安全防护的效率。
263 0