POSTGRESQL 一个“大” SQL 的优化历险记
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);
4 验证结果
打开timing 我们查看添加索引和取消索引后的执行情况。我们分别针对,添加索引,和去掉我们索引的情况进行了分析,整体的结果在不使用合适的索引的情况下,整体的查询在100毫秒左右 ,在使用了对应的索引后,整体查询的时间在9 毫秒左右,性能提高了10倍。
5 探究原因
按照开发的思路,他建立的索引 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 的优化历险记相关推荐
- sql 一个字段在另外一个表没出现_都9012年啦,不懂得这些SQL语句优化,你是要吃大亏的...
引言 数据库的性能优化技术一直是个老生常谈的问题,不管是MySQL.SQL Server还是Oracle. 对于我们IT开发人员和运维人员,掌握常用的SQL 优化语句是非常必要的,它可以使你的工作变得 ...
- 数据库优化:SQL高性能优化指南,助你成就大神之路!
1.参数是子查询时,使用 EXISTS 代替 IN 如果 IN 的参数是(1,2,3)这样的值列表时,没啥问题,但如果参数是子查询时,就需要注意了.比如,现在有如下两个表: 现在我们要查出同时存在于两 ...
- 一个系列搞懂Mysql数据库12:从实践sql语句优化开始
Table of Contents 字段 索引 查询SQL 引擎 MyISAM InnoDB 0.自己写的海量数据sql优化实践 mysql百万级分页优化 普通分页 优化分页 总结 除非单表数据未来会 ...
- postgresql大表join优化
postgresql大表join优化 一.背景 1.数据量: 表名 数据量 f_invoice 87346130 f_invoice_item 97535867 2.索引: 表:f_invoice_i ...
- 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 的子查询 ...
- sql like 多个条件_都9012年啦,不懂得这些SQL语句优化,你是要吃大亏的
引言 数据库的性能优化技术一直是个老生常谈的问题,不管是MySQL.SQL Server还是Oracle. 对于我们IT开发人员和运维人员,掌握常用的SQL 优化语句是非常必要的,它可以使你的工作变得 ...
- 连接impala出现method not supported_Impala在网易大数据的优化和实践
文章作者:温正湖 网易杭研 编辑整理:张博 出品平台:DataFunTalk 导读:网易大数据平台的底层数据查询引擎,选用了Impala作为OLAP查询引擎,不但支撑了网易大数据的交互式查询与自助分析 ...
- Impala在网易大数据的优化和实践
导读:网易大数据平台的底层数据查询引擎,选用了Impala作为OLAP查询引擎,不但支撑了网易大数据的交互式查询与自助分析,还为外部客户提供了商业化的产品与服务.今天将为大家分享下Impala在网易大 ...
- Impala 在网易大数据的优化和实践
导读: 网易大数据平台的底层数据查询引擎,选用了 Impala 作为 OLAP 查询引擎,不但支撑了网易大数据的交互式查询与自助分析,还为外部客户提供了商业化的产品与服务.今天将为大家分享下 Impa ...
- Citus 分布式 PostgreSQL 集群 - SQL Reference(查询处理)
一个 Citus 集群由一个 coordinator 实例和多个 worker 实例组成. 数据在 worker 上进行分片和复制,而 coordinator 存储有关这些分片的元数据.向集群发出的所 ...
最新文章
- Android基础--tools:context=.TestActivity作用
- IDEA2021.3无法创建测试类解决方法
- 全球及中国燃料乙醇行业产量规模及供需前景分析报告2021-2027年
- [设计模式笔记]3.单例模式
- cocos 制作动态生成内容的列表_零代码工具,让你在线轻松制作交互内容!
- 专业英语笔记:Install and Use Python
- 速度提升3000倍,微软FastNeRF首次实现200FPS高保真神经渲染
- hist函数--matplotlib
- 微信小程序云函数发天气预报
- win10如何切换计算机用户,Windows10系统下切换用户的多种技巧
- 注册邮箱验证激活技术
- 机器学习sklearn-逻辑回归
- Debian 10.2命令安装Nvidia显卡驱动成功,问题回顾
- 阿里云直播生成推流和播流地址类
- AMOLED原理介紹
- Open edX数据结构Mysql edxapp
- 022 利用头皮脑电信号预测癫痫发作2021
- MosFET/FinFET/GAFET ——鳍式晶体管还能走多远
- 云计算课程作业专业词汇
- 同程旅行大数据集群在 Kubernetes 上的服务化实践
热门文章
- Java:实现动态规划的4个经典题型,你都会吗?拒绝做优秀的码农
- ORR R0,R0,#R1_nF:OR:R1_iA
- 单片机c语言设计奥运五环,如何用C语言程序来设计奥运五环图案.doc
- 浏览器主页被篡改解决方法
- 浏览器首页被恶意篡改
- 基于STM32的人体红外测温
- be 动词 、 一般动词的过去式
- 三维地图开发三维地图服务器
- C# 切割超级大图(.bmp)[1G以上超大图片分块加载代码]
- 转:明茨伯格:组织不需要英雄,只需要有雅量的领导