首页 > 数据库 >POSTGRESQL SQL 语句案例,一场由LIMIT 1 引发的“奇怪异像”

POSTGRESQL SQL 语句案例,一场由LIMIT 1 引发的“奇怪异像”

时间:2023-06-22 12:06:17浏览次数:64  
标签:语句 shop POSTGRESQL 异像 btpg LIMIT gb ticket id


开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。

POSTGRESQL   SQL 语句案例,一场由LIMIT 1 引发的“奇怪异像”_postgresql

最近一段工作很少优化SQL ,实际

上7-8年前的确有一段疯狂优化的“美好时光”。 最近一个同事提出一个问题,他的一个POSTGRESQL 的SQL 在运行中因为客户的需要,将语句添加limit 1 ,但是在添加完毕后,整体语句运行时间超过原有的语句少则9倍,多则20多倍,从不到2秒,变成了23秒。

下面是语句的修改版,不少部分已经改名了。

SELECT
bizzz.* 
FROM
(
SELECT
1 AS "bizzzType",
os.NAME "deFromName",
gb.title "ticketName",
gb.market_price "marketPrice",
gb.price price,
gb.discount_rate * 100 "discountRate",
gb.income_money "ticketIncomeMoney",
gb.div_ticket_name "divTicketName",
btpg.ticket_count "ticketCount",
btpg.pay_money "payMoney",
( gb.market_price - gb.price ) * btpg.ticket_count "discMoney",
CASE 
WHEN btpg.ticket_sale * btpg.ticket_count > btpg.pay_money 
THEN
btpg.pay_money 
ELSE btpg.ticket_sale * btpg.ticket_count 
END "incomeMoney",
shop.ID AS "shopId",
shop.NAME AS "shopName",
btpg.no_give_change "noGiveChange",
btpg.bs_id "bsId",
bb.code "bsCode",
btpg.ticket_code "ticketCode",
btpg.create_time "useTime",
bb.settle_bizzz_date "settlebizzzDate",
COALESCE ( btpg.income_overchange, 0 ) "incomeOverChange" ,
pw_detail_id as "ticketRowId"
FROM
(SELECT
bs_id,
ticket_count,
ticket_sale,
ticket_value,
pay_money,
payc_id,
ticket_id,
create_shop_id,
pw_detail_id,
no_give_change,
create_time,
REPLACE ( REPLACE ( REPLACE ( REPLACE ( ticket_code_serials, '["', '' ), '"]', '' ), '"', '' ), ',', ';' ) AS ticket_code,
income_overchange 
FROM  bizzz_ts_pw_gb 
WHERE create_shop_id IN ( SELECT ID FROM dbi_shop WHERE center_id = 83726 AND manage_type_id IN ( 301, 302, 304 ) ) 
AND modify_time >= '2023-03-02 00:00:00' 
AND modify_time <'2023-03-03 00:00:00' 
AND delflg = 0 
AND settle_state = 1 
) btpg
INNER JOIN (SELECT ID,code,settle_bizzz_date  FROM
bizzz_bs 
WHERE
create_shop_id IN ( SELECT ID FROM dbi_shop WHERE center_id = 83726 AND manage_type_id IN ( 301, 302, 304 ) ) AND settle_time >='2023-03-02 00:00:00'  AND settle_time < '2023-03-03 00:00:00'AND STATE = 1 
AND delflg = 0 ) bb ON btpg.bs_id = bb.
ID
INNER JOIN ( SELECT ID FROM arch_pay c WHERE payc_type_id = 509 ) ap ON btpg.payc_id = ap.ID
LEFT JOIN ( SELECT deal_id, belong_shop_id, title, market_price, price, discount_rate, income_money, synchron_time, div_ticket_name 
FROM o2o_wuu_gb_ticket 
WHERE create_shop_id = 83726 ) gb ON btpg.ticket_id = gb.deal_id AND btpg.create_shop_id = gb.belong_shop_id
INNER JOIN ( SELECT deal_id, belong_shop_id, MAX ( synchron_time ) synchron_time 
FROM o2o_wuu_gb_ticket 
WHERE create_shop_id = 83726 GROUP BY belong_shop_id, deal_id ) gbTicketFilter ON gb.deal_id = gbTicketFilter.deal_id 
AND gb.belong_shop_id = gbTicketFilter.belong_shop_id AND gb.synchron_time = gbTicketFilter.synchron_time
INNER JOIN ( SELECT payc_id, NAME FROM arch_o2o_seller ) os ON os.payc_id = btpg.payc_id
LEFT JOIN dbi_shop shop ON shop.ID = btpg.create_shop_id 
) bizzz 
ORDER BY
"shopName","ticketName","marketPrice","ticketRowId";
 limit 1;

首先比对执行计划,虽然仅仅是一个limit 的添加但是整体的执行计划都改变了,

POSTGRESQL   SQL 语句案例,一场由LIMIT 1 引发的“奇怪异像”_数据_02

改变发现1 

在没有添加LIMIT 1的情况下,整体的语句的查询中是没有 大量的seq scan ,基本上整体整体的语句中对于数据处理都是在index scan.

改变发现2 

在添加LIMIT 1 后,整体的语句的执行顺序,与原先的顺序不同了,不添加limit  1  ,首先处理了语句中最大的表,由于最大的表的数据过滤的条件多,所以对于排除数据起到了相关的提前过滤的作用。

而添加了limit 1后,整体的语句处理的顺序和语句撰写的从上到下的语句关联的顺序基本一致,导致处理从小表开始进行预先处理。最终导致小表驱动大表的情况。

改变发现3

在不添加LIMIT 1 的情况下,整体上层的 语句中的计算部分使用中由于,执行顺序的问题,让大表的数据过滤后,在被上层使用,减少了计算的数据量,而反观添加了LIMIT 1 后的语句,计算中过滤的行较多。导致计算成本升高。

sort  的部分中的语句执行的整体计划的顺序,与加入了limit 的整体计划的顺序是错位的。

SORT 没有limit 的部分,中的驱动表与驱动表之间是通过index 关联的方式进行的处理。

POSTGRESQL   SQL 语句案例,一场由LIMIT 1 引发的“奇怪异像”_数据库_03

limit   而在末尾加入了limit 后,整体的执行计划,驱动表和被驱动表的位置互换了,通知对于驱动表的执行的方式变为了扫描方式。

POSTGRESQL   SQL 语句案例,一场由LIMIT 1 引发的“奇怪异像”_数据库_04

由于语句是否的复杂,如果要非常的明白的分析出来,则需要很长的时间,实际上抓住了两点

1 复杂的语句如果使用了limit 1,需要注意在POSTGRESQL 13中的语句是否还能通过优化器,优先判断对数据进行大表过滤,由于使用LIMIT 1 这样的语句,导致语句优化和执行系统对于提取的数据的有序性判断过于复杂,导致优化器,按照语句的撰写方式进行了数据的执行,保证提取数据的优秀和有效性,同时多个不同表的字段最终进行排序,加重了执行分析器的负担,导致执行分析器躺平,做了保守的执行计划的操作。

2  业务逻辑是否需要对于LIMIT 1 的语句进行排序的分析,这点非常有必要,在语句的执行中大部分语句的撰写尤其类似这样OLAP 很重的语句一般都带有排序,但是如果只是在结果中取一个结果  limit 1 则是否有必要进行排序这点非常有必要进行确认。一般根据语句的逻辑,是没有必要进行排序在LIMIT 1,因为你是随机取和顺序是无关的。

这个语句实际上最后优化的手段就是去掉ORDER BY ,最终去掉后比原先的同样的条件,执行的效率提高了  62倍,在 150毫秒左右就将结果计算出来,同时还有一个因素是如果你在撰写语句的时候带有LIMIT 1 则POSTGRESQL 的优化器会优先选择计算成本中,第一个启动成本较低的执行计划而不是整体成本较低的执行计划,所以建议在一些语句中,考虑业务的需求的情况下,分析是否有必要进行排序,慎用在复杂语句中的排序导致的执行效率低下的问题。

另外这里还有一个在使用LIMIT 1 后导致的PG执行计划的倾向性的问题,你造吗 !

POSTGRESQL   SQL 语句案例,一场由LIMIT 1 引发的“奇怪异像”_postgresql_05

POSTGRESQL   SQL 语句案例,一场由LIMIT 1 引发的“奇怪异像”_postgresql_06

POSTGRESQL   SQL 语句案例,一场由LIMIT 1 引发的“奇怪异像”_数据库_07

标签:语句,shop,POSTGRESQL,异像,btpg,LIMIT,gb,ticket,id
From: https://blog.51cto.com/u_14150796/6534546

相关文章

  • PostgreSQL 15 stats collector 在取消后是如何实现的原有功能的
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。在POSTGRESQL15有一个重要的功能去掉了statscollector在说为什么去掉这个statscollector的问题前,我们先得弄清出statscoll......
  • POSTGRESQL 和 MYSQL 到底应该不应该控制活跃连接
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql ,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。最近群里某个同学的提问,引起的本篇文章,关于数据库连接的部分,没有废话,我们先针对MYSQL来说说数据库连接的部分。首先MYSQL的客......
  • POSTGRESQL 自动搜索所有逻辑库中的无用索引自动化脚本实现
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。前两天腾出点时间,打算整理一下POSTGRESQL公司的数据库的无用的索引的问题,写了一个SQL通过SQL来获取这些数据库的无用索引,但头......
  • PostgreSQL 15 让多年被DISS的PG 安全画上圆满的句号
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。提起POSTGRESQL中的安全问题其中最容易被人Diss的最大BUG并不是autovacuum 之类的部分,排在首位的被DISS的最大的问题是安全的......
  • POSTGRESQL postgresql 升级的需求来自哪里
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题(本篇的思路来自于,盘古云课堂PG152023年2月18日晚,PG15升级问题大讨论稿)说起POSTGRESQL的升级问题,很多同学会问,升级POSTGRESQL......
  • POSTGRESQL 再说 PGBOUNCER 如何部署的问题
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。最近得到与PGBOUNCER的一个问题,问题大体上是这样描述的,一台POSTGRESQL的服务器,2000个maxconnection,同时安装了4个pgbouncer在......
  • PostgreSQL 16 三则 “新功能更新”
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。POSTGRESQL15刚刚推出不久,而POSTGRESQL16的新功能也已经在路上了,下面说说PG16已经确认有的3个新功能。1PG_DUMP压缩相对......
  • POSTGRESQL SQL 优化,不建立索引,不调整参数,不修改SQL的另类方式
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,软件架构师,软件开发大佬,可以解决你的问题。在MYSQL中很少听说过自建统计信息,实际上在其他数据库中,创建统计信息的方式和需求都是有的,尤其处理复杂SQ......
  • output clipped, log limit 1MiB reached
    docker构建中会限制容器日志的总大小当一个步骤的日志记录速度超过40MB/s时BuildKit会暂停并等待某些日志被写入磁盘。当一个步骤输出超过16MB的日志时,BuildKit会将它截断并创建一个新的日志文件。修改参数env.BUILDKIT_STEP_LOG_MAX_SIZE=-1env.BUILDKIT_STEP_......
  • PG-DBA培训03:Linux平台PostgreSQL安装配置与管理入门
    一、风哥PG-DBA培训03:Linux平台PostgreSQL安装配置与管理入门本课程由风哥发布的基于PostgreSQL数据库的系列课程,本课程属于PostgreSQL数据库实战入门与安装配置阶段之Linux平台PostgreSQL安装配置与管理入门课程,学完本课程可以掌握基于Linux平台的PostgreSQL项目规划,PostgreSQL......