德哥的优化思路巨牛逼,这种递归思维真的太吊了,我目前就缺递归思路。

下面SQL1000W行数据,列的选择性很低,只有两个值('1'和'11')都是字符串类型,'1'只有一条数据,'11'有9999999行数据。

慢SQL:

select distinct col from tt;

                                                      QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=169247.11..169247.12 rows=1 width=3) (actual time=5082.733..5082.735 rows=2 loops=1)
Group Key: col
-> Seq Scan on tt (cost=0.00..144247.29 rows=9999929 width=3) (actual time=0.005..275.906 rows=10000000 loops=1)
Planning Time: 0.365 ms
Execution Time: 5082.772 ms
(5 行记录)

CTE递归优化:

WITH RECURSIVE t AS (
(SELECT col FROM tt ORDER BY col LIMIT 1)
UNION ALL
SELECT (SELECT col FROM tt WHERE col > t.col ORDER BY col LIMIT 1)
FROM t
WHERE t.col IS NOT NULL
)
SELECT col FROM t WHERE col IS NOT NULL; QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------
CTE Scan on t (cost=50.84..52.86 rows=100 width=38) (actual time=0.024..0.079 rows=2 loops=1)
Filter: (col IS NOT NULL)
Rows Removed by Filter: 1
CTE t
-> Recursive Union (cost=0.43..50.84 rows=101 width=38) (actual time=0.022..0.076 rows=3 loops=1)
-> Limit (cost=0.43..0.46 rows=1 width=3) (actual time=0.021..0.021 rows=1 loops=1)
-> Index Only Scan using idx_1_2_tt on tt tt_1 (cost=0.43..260443.37 rows=9999929 width=3) (actual time=0.020..0.020 rows=1 loops=1)
Heap Fetches: 0
-> WorkTable Scan on t t_1 (cost=0.00..4.84 rows=10 width=38) (actual time=0.017..0.017 rows=1 loops=3)
Filter: (col IS NOT NULL)
Rows Removed by Filter: 0
SubPlan 1
-> Limit (cost=0.43..0.46 rows=1 width=3) (actual time=0.024..0.024 rows=0 loops=2)
-> Index Only Scan using idx_1_2_tt on tt (cost=0.43..95149.36 rows=3333310 width=3) (actual time=0.024..0.024 rows=0 loops=2)
Index Cond: (col > (t_1.col)::text)
Heap Fetches: 0
Planning Time: 0.096 ms
Execution Time: 0.096 ms
(18 行记录)

里面的逻辑是:

(SELECT col FROM tt ORDER BY col LIMIT 1)

  根节点通过order by 升序 找到最小的一条数据作为起点。

递归查询:

SELECT (SELECT col FROM tt WHERE col > t.col ORDER BY col LIMIT 1)
FROM t
WHERE t.col IS NOT NULL

  在第一次迭代中,CTE t 包含值'1'。这个查询将在tt表中寻找col大于'1'的最小值。在数据集中,这将是'11'。

  在第二次迭代,CTE t 将包含'11'。此时,查询将尝试找到大于'11'的最小值,但没有这样的值,所以返回NULL。

递归结束:
  当递归查询返回NULL时,递归结束。这时,CTE t 将包含'1'和'11',返回和distinct 一样逻辑的数据。

理解了整个逻辑后我都吓尿了,就一道算法题,确实要跟巨佬学习才行,加深递归思维。

pg distinct 改写递归优化(德哥的思路)的更多相关文章

  1. 德哥的PostgreSQL私房菜 - 史上最屌PG资料合集

    德哥的PostgreSQL私房菜 - 史上最屌PG资料合集

  2. 云栖专辑|阿里开发者们的第二个感悟:PG大V德哥的使命感与开放心态

    摘要: 2018年12月20日,云栖社区3岁.阿里巴巴常说“晴天修屋顶”,所以我们特别制作了这个专辑——分享给开发者们20个阿里故事,50本书籍. 2015年12月20日,云栖社区上线.2018年12 ...

  3. 德哥PostgreSQL学习资料汇总(转)

    文章来自:https://yq.aliyun.com/articles/59251?spm=5176.100239.bloglist.95.5S5P9S 德哥博客新地址:https://billtia ...

  4. js递归优化

    递归优化 递归在我们平时撸码中会经常用到,不过可能很多人不知道递归的弊端,就是会导致调用栈越来越深.如果没有节制的使用递归可能会导致调用栈溢出. 那什么是递归呢? 递归调用是一种特殊的嵌套调用,是某个 ...

  5. 使用 CUDA 进行计算优化的两种思路

    前言 本文讨论如何使用 CUDA 对代码进行并行优化,并给出不同并行思路对均值滤波的实现. 并行优化的两种思路 思路1: global 函数 在 global 函数中创建出多个块多个线程对矩阵每个元素 ...

  6. 第七篇:使用 CUDA 进行计算优化的两种思路

    前言 本文讨论如何使用 CUDA 对代码进行并行优化,并给出不同并行思路对均值滤波的实现. 并行优化的两种思路 思路1: global 函数 在 global 函数中创建出多个块多个线程对矩阵每个元素 ...

  7. [06] 优化C#服务器的思路和工具的使用

    优化C#服务器的思路和工具的使用 优化服务器之前, 需要先对问题的规模做合理的预估, 然后对关键的数据做采样, 做对比, 看和自己的预估是否一致, 误差大在什么地方, 是预估的不对, 还是系统实现有问 ...

  8. [转]德哥的PostgreSQL私房菜 - 史上最屌PG资料合集

    链接地址:https://yq.aliyun.com/articles/59251

  9. 【PostgreSQL】资料索引(来源:德哥)

    PostgreSQL 多应用场景实践 - 沙箱实验 https://github.com/digoal/blog/blob/master/201805/20180524_02.md 一.GIS < ...

  10. javascript memoization递归优化

    memoize优化递归 function createRec(callback, cache) { cache = cache || []; var rec = function(n) { (n in ...

随机推荐

  1. 5.1 C/C++ 使用文件与指针

    C/C++语言是一种通用的编程语言,具有高效.灵活和可移植等特点.C语言主要用于系统编程,如操作系统.编译器.数据库等:C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统.图形用户界面 ...

  2. 基本数据类型(primitive type)

    数据类型 数据类型分为基本数据类型(primitive type)和引用数据类型(reference type) 基本数据类型(primitive type) 数值类型 整数类型 浮点类型 字符类型 ...

  3. Java并发(十)----线程之守护线程

    默认情况下,Java 进程需要等待所有线程都运行结束,才会结束.有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束. 例: log.debug(&q ...

  4. Java并发(七)----线程sleep、yield、线程优先级

    1.sleep 与 yield sleep 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞) 其它线程可以使用 interrupt 方法打断正在睡眠的线 ...

  5. 利用ogg实现oracle到kafka的增量数据实时同步

    前言 ogg即Oracle GoldenGate是Oracle的同步工具,本文讲如何配置ogg以实现Oracle数据库增量数据实时同步到kafka中,其中同步消息格式为json. 下面是我的源端和目标 ...

  6. 从零开始的 dbt 入门教程 (dbt core 开发进阶篇)

    引 在上一篇文章中,我们花了专门的篇幅介绍了 dbt 更多实用的命令,那么我们继续按照之前的约定来聊 dbt 中你可能会遇到的疑惑以及有用的概念,如果你是 dbt 初学者,我相信如下知识点一定会对你有 ...

  7. JS Leetcode 33. 搜索旋转排序数组题解,图解旋转数组中的二分法

    壹 ❀ 引 本来今天(2021.4.7)的每日一题是81. 搜索旋转排序数组 II,但今天工作很忙,下班人基本累个半死,题目别说按照二分法的思路做不出来,连题解看了会都没法沉下心去看,不过得到的信息是 ...

  8. Vdbench 使用说明

    一. vdbench简介 vdbench是一个 I/O 工作负载生成器,用于验证数据完整性和度量直接附加和网络连接的存储的性能.它是一个免费的工具,容易使用,而且常常用于测试和基准测试. 可以使用vd ...

  9. Redis+Lua实现简易的秒杀抢购

    1  商品抢购 主要逻辑是:减库存,记录抢购成功的用户 @RestController public class DemoController { @Resource private StringRe ...

  10. Wireguard笔记(二) 命令行操作

    目录 Wireguard笔记(一) 节点安装配置和参数说明 Wireguard笔记(二) 命令行操作 Wireguard笔记(三) lan-to-lan子网穿透和多网段并存 命令行操作 创建wg0网卡 ...