POSTGRESQL 在SQL 的处理能力上,在开源数据库上面,难逢敌手, 而开始为难POSTGRESQL的语句也就开始层出不穷。下面的SQL可以称之为一个"BIG" SQL。(基于信息保护机制,部分语句中的名字被改变)

WITH wmsj AS (SELECT wod.de_from AS deFrom,
                SUM(wop.income) AS incomeMoney
                FROM o2o_public AS wop INNER JOIN wuu_o2o_delivery AS wod ON wop.de_id = wod.de_id
                WHERE wop.modify_time BETWEEN CAST('2022-xx-xx 06:00:00' AS TIMESTAMP) AND CAST('2022-xx-xx 13:23:05.35' AS TIMESTAMP) AND
                wop.create_shop_id = 'xxxx' AND wop.receive_pos_id = '246000000000000001' AND
                (wop.state NOT IN(3,6,11) AND
                wop.refund_state   <>   2)
                GROUP BY wod.de_from
                UNION ALL
                SELECT wod.de_from AS deFrom,
                - SUM(wopb.pr_money) AS incomeMoney
                FROM wuu_o2o_partback AS wopb INNER JOIN o2o_public AS wop ON wopb.de_id = wop.de_id AND wop.receive_pos_id = '246000000000000001' AND
                (wop.state NOT IN(3,6,11) AND
                wop.refund_state <> 2)
                INNER JOIN o2o_delivery AS wod ON wop.de_id = wod.de_id
                WHERE wopb.modify_time BETWEEN CAST('2022-07-07 06:00:00' AS TIMESTAMP) AND CAST('2022-07-07 13:23:05.35' AS TIMESTAMP) AND
                wopb.create_shop_id = '2460' AND
                wopb.pr_state = 2 AND
                wopb.delflg = 0
                GROUP BY wod.de_from)
                SELECT wmsj.deFrom AS deFrom,
                bos.name AS deName,
                SUM(wmsj.incomeMoney) AS incomeMoney
                FROM o2o_setting AS bos RIGHT OUTER JOIN wmsj ON bos.type = wmsj.deFrom
                GROUP BY wmsj.deFrom,
                bos.name
                ORDER BY wmsj.deFrom;

面对这样的SQL如何进行分析优化,手段在哪里,我们来捋一捋。

1  拆

SQL 都是一堆堆的逻辑进行组合的,通过组合达到整体的逻辑需求,而这样凭着逻辑撰写的SQL ,有一个问题,思路的问题,什么问题,一条SQL 解决所有问题的思路。那么优化时,必须将这些SQL 拆解,通过拆解,将问题缩小化,逐个核对和击破问题。

1

SELECT wod.de_from AS deFrom,
                SUM(wop.income) AS incomeMoney
                FROM o2o_public AS wop INNER JOIN wuu_o2o_delivery AS wod ON wop.de_id = wod.de_id
                WHERE wop.modify_time BETWEEN CAST('2022-07-07 06:00:00' AS TIMESTAMP) AND CAST('2022-07-07 13:23:05.35' AS TIMESTAMP) AND
                wop.create_shop_id = '2460' AND wop.receive_pos_id = '246000000000000001' AND
                (wop.state NOT IN(3,6,11) AND
                wop.refund_state   <>   2)
                GROUP BY wod.de_from;
  2             
                SELECT wod.de_from AS deFrom,
                - SUM(wopb.pr_money) AS incomeMoney
                FROM o2o_partback AS wopb INNER JOIN wuu_o2o_public AS wop ON wopb.de_id = wop.de_id AND wop.receive_pos_id = '246000000000000001' AND
                (wop.state NOT IN(3,6,11) AND
                wop.refund_state <> 2)
                INNER JOIN o2o_delivery AS wod ON wop.de_id = wod.de_id
                WHERE wopb.modify_time BETWEEN CAST('2022-07-07 06:00:00' AS TIMESTAMP) AND CAST('2022-07-07 13:23:05.35' AS TIMESTAMP) AND
                wopb.create_shop_id = '2460' AND
                wopb.pr_state = 2 AND
                wopb.delflg = 0
                GROUP BY wod.de_from;

先拆出两个SQL 。

然后我们开始针对这两个SQL 开始看他们的执行计划

GroupAggregate  (cost=532.70..532.72 rows=1 width=36)
   Group Key: wod.de_from
   ->  Sort  (cost=532.70..532.70 rows=1 width=10)
         Sort Key: wod.de_from
         ->  Nested Loop  (cost=1.00..532.69 rows=1 width=10)
               ->  Index Scan using idx_o2o_public_3 on o2o_public wop  (cost=0.56..530.02 rows=1 width=10)
                     Index Cond: ((create_shop_id = 2460) AND (receive_pos_id = '246000000000000001'::bigint))
                     Filter: ((modify_time >= '2022-xx-xx 06:00:00'::timestamp without time zone) AND (modify_time <= '2022-07-07

13:23:05.35'::timestam
p without time zone) AND (refund_state <> 2) AND (state <> ALL ('{3,6,11}'::integer[])))
               ->  Index Scan using de_id_indix on wuu_o2o_delivery wod  (cost=0.44..2.66 rows=1 width=8)
                     Index Cond: (de_id = wop.de_id)

2  拿到SQL 中表的数据量,以及索引,和采样率。

2000万的表

表中的索引

"pk_o2o_public" PRIMARY KEY, btree (id)
    "de_id2_indix" btree (de_id)
    "idx_op_createdate" btree (create_date)
    "idx_public_de_no" btree (de_no)
    "idx_o2o_public_1" btree (create_shop_id, create_time, de_id, state, refund_state, delflg)
    "idx_o2o_public_2" btree (modify_time, receive_pos_id, create_shop_id)
    "idx_o2o_public_3" btree (create_shop_id, receive_pos_id, create_time)
    "idx_o2o_public_de_id" btree (de_id)

这里关注两个索引  idx_wuu_o2o_public_2  和  idx_wuu_o2o_public_3

在分析索引前,我们先看看查询条件里面的字段有哪些,这些字段的分布情况如何

modify_time  
 create_shop_id
 receive_pos_id
 state
 refund_state
 de_from

1  modify_time

correlation            | 0.999602

2  create_shop_id

correlation            | 0.786221

3  receive_pos_id

correlation            | 0.784747

4  state

correlation            | 0.858308

5  refund_state

correlation            | 0.963647

3 发现问题解决问题

按照原理,我们希望我们的cost 是低的,因为查询中 “开发” 的同学建立索引是按照查询语句的条件的顺序建立的,但是并没有走他们要的索引。随即我们根据POSTGRESQL 查询语句与索引之间的规范,添加了更合适的索引,整体的COST 值降低了不少。

create index idx_wuu_o2o_public_create_receive_modify on wuu_o2o_public(create_shop_id,receive_pos_id,modify_time);

验证结果

打开timing 我们查看添加索引和取消索引后的执行情况。我们分别针对,添加索引,和去掉我们索引的情况进行了分析,整体的结果在不使用合适的索引的情况下,整体的查询在100毫秒左右 ,在使用了对应的索引后,整体查询的时间在9 毫秒左右,性能提高了10倍。

探究原因

按照开发的思路,他建立的索引 idx_wuu_o2o_public_2 是符合他思路的索引    "idx_wuu_o2o_public_2" btree (modify_time, receive_pos_id, create_shop_id)  而实际上走的索引,缺失下面的索引    "idx_wuu_o2o_public_3" btree (create_shop_id, receive_pos_id, create_time)

这里提出一个问题,为什么不走 2 号索引,研其原因,

1  对于一个算法来说,一个不确定的事情,是不可能被使用的,范围这样的字段就是一个不确定的事情,你的范围可大可小,算法无法判断你每次的查询的范围,所以这不能作为一个 “恒定的量”

2  基于数据库的分析器,是要算成本的,基于范围的成本估算困难,这里建议,产出索引不是简单就凭着,查询的顺序就可以建立的,一个索引的建立

1  查看统计信息中的 n_distinct

2  查看统计信息中的correlation

3  根据你查询的符号方式来确认

基于以上三个部分,来初步确认你的POSTGRESQL 的索引该怎么建立。

POSTGRESQL 一个“大” SQL 的优化历险记相关推荐

  1. sql 一个字段在另外一个表没出现_都9012年啦,不懂得这些SQL语句优化,你是要吃大亏的...

    引言 数据库的性能优化技术一直是个老生常谈的问题,不管是MySQL.SQL Server还是Oracle. 对于我们IT开发人员和运维人员,掌握常用的SQL 优化语句是非常必要的,它可以使你的工作变得 ...

  2. 数据库优化:SQL高性能优化指南,助你成就大神之路!

    1.参数是子查询时,使用 EXISTS 代替 IN 如果 IN 的参数是(1,2,3)这样的值列表时,没啥问题,但如果参数是子查询时,就需要注意了.比如,现在有如下两个表: 现在我们要查出同时存在于两 ...

  3. 一个系列搞懂Mysql数据库12:从实践sql语句优化开始

    Table of Contents 字段 索引 查询SQL 引擎 MyISAM InnoDB 0.自己写的海量数据sql优化实践 mysql百万级分页优化 普通分页 优化分页 总结 除非单表数据未来会 ...

  4. postgresql大表join优化

    postgresql大表join优化 一.背景 1.数据量: 表名 数据量 f_invoice 87346130 f_invoice_item 97535867 2.索引: 表:f_invoice_i ...

  5. PostgreSQL SQL中的ALL,ANY,SOME的用法,sql查询速度优化,sql运行优化

    PostgreSQL SQL中的ALL,ANY,SOME的用法,sql查询速度优化,sql运行优化 准备两个表: --T1(2,3) --T2(1,2,3,4)--ALL,ANY,SOME 的子查询 ...

  6. sql like 多个条件_都9012年啦,不懂得这些SQL语句优化,你是要吃大亏的

    引言 数据库的性能优化技术一直是个老生常谈的问题,不管是MySQL.SQL Server还是Oracle. 对于我们IT开发人员和运维人员,掌握常用的SQL 优化语句是非常必要的,它可以使你的工作变得 ...

  7. 连接impala出现method not supported_Impala在网易大数据的优化和实践

    文章作者:温正湖 网易杭研 编辑整理:张博 出品平台:DataFunTalk 导读:网易大数据平台的底层数据查询引擎,选用了Impala作为OLAP查询引擎,不但支撑了网易大数据的交互式查询与自助分析 ...

  8. Impala在网易大数据的优化和实践

    导读:网易大数据平台的底层数据查询引擎,选用了Impala作为OLAP查询引擎,不但支撑了网易大数据的交互式查询与自助分析,还为外部客户提供了商业化的产品与服务.今天将为大家分享下Impala在网易大 ...

  9. Impala 在网易大数据的优化和实践

    导读: 网易大数据平台的底层数据查询引擎,选用了 Impala 作为 OLAP 查询引擎,不但支撑了网易大数据的交互式查询与自助分析,还为外部客户提供了商业化的产品与服务.今天将为大家分享下 Impa ...

  10. Citus 分布式 PostgreSQL 集群 - SQL Reference(查询处理)

    一个 Citus 集群由一个 coordinator 实例和多个 worker 实例组成. 数据在 worker 上进行分片和复制,而 coordinator 存储有关这些分片的元数据.向集群发出的所 ...

最新文章

  1. Android基础--tools:context=.TestActivity作用
  2. IDEA2021.3无法创建测试类解决方法
  3. 全球及中国燃料乙醇行业产量规模及供需前景分析报告2021-2027年
  4. [设计模式笔记]3.单例模式
  5. cocos 制作动态生成内容的列表_零代码工具,让你在线轻松制作交互内容!
  6. 专业英语笔记:Install and Use Python
  7. 速度提升3000倍,微软FastNeRF首次实现200FPS高保真神经渲染
  8. hist函数--matplotlib
  9. 微信小程序云函数发天气预报
  10. win10如何切换计算机用户,Windows10系统下切换用户的多种技巧
  11. 注册邮箱验证激活技术
  12. 机器学习sklearn-逻辑回归
  13. Debian 10.2命令安装Nvidia显卡驱动成功,问题回顾
  14. 阿里云直播生成推流和播流地址类
  15. AMOLED原理介紹
  16. Open edX数据结构Mysql edxapp
  17. 022 利用头皮脑电信号预测癫痫发作2021
  18. MosFET/FinFET/GAFET ——鳍式晶体管还能走多远
  19. 云计算课程作业专业词汇
  20. 同程旅行大数据集群在 Kubernetes 上的服务化实践

热门文章

  1. Java:实现动态规划的4个经典题型,你都会吗?拒绝做优秀的码农
  2. ORR R0,R0,#R1_nF:OR:R1_iA
  3. 单片机c语言设计奥运五环,如何用C语言程序来设计奥运五环图案.doc
  4. 浏览器主页被篡改解决方法
  5. 浏览器首页被恶意篡改
  6. 基于STM32的人体红外测温
  7. be 动词 、 一般动词的过去式
  8. 三维地图开发三维地图服务器
  9. C# 切割超级大图(.bmp)[1G以上超大图片分块加载代码]
  10. 转:明茨伯格:组织不需要英雄,只需要有雅量的领导