PostgreSQL SQL优化用兵法,优化后提高 140倍速度

开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,可以解决你的问题。加群请联系 liuaustin3 ,(共2720人左右 1 + 2 + 3 + 4 +5 + 6 + 7 + 8 +9)(1 2 3 4 5 6群均已爆满,7群430+,开8群170+ 9群)

今天的领悟,人生没有白走的,对错都算数,做完一些事情,经常会后悔,如果我当时选择了A,就好了,可我当时选择的是B,然后不断地悔恨。人的眼睛都是长在前面的,选择就选择了,错了就错了,错了吸收教训,不要再犯就好,当时我也站在迷雾中,也很迷茫,哪怕在给我一次机会,还是会选择B,与其后悔,不如持续修炼--- 一个现实世界的“申公豹”留言。

386bba3193da5f630a11ce923228b645.png

SQL 的优化是DBA工作的主题,这里我想以这篇文章,将SQL优化的方式方法,以及程序员的撰写SQL的问题说清楚,如果有不周之处还请各位老师指点一二。

SQL 本身是什么,完成什么功能这点做DBA的同学要清晰。

1  SQL是程序完成数据输入,输出的必经之路

2  SQL是程序搜取数据不多方案中的最有效的数据提取方案

3  SQL除了必备的数据提取功能,还有数据处理和计算的功能

4  SQL可能完成了程序功能的一部分,甚至是程序核心的一部分

5  SQL是大部分程序中的热点,是一个程序运行好坏的至关重要的一部分

明白了这些SQL的运行的好坏与程序之间的关系就明确了。

为什么SQL就不能一次性写好

1  程序生成的SQL,通过程序将代码转换为SQL,这样的SQL明显不能进行优化的写法实现,在系统初步运行的过程可以接受这样的写法,但在系统高负载的情况下,则这样的SQL就是问题的爆发点。

2  乱建索引,这点很常见,索引的好坏影响SQL的运行。一个好的索引可以助力SQL快速的运行,一个差劲的索引是SQL运行的阻碍,乱建的方式

1  每个字段建立一个索引

2  将很多的字段建立索引

3  不按照语句的规律和查询的字段顺序和方式建立索引

4  索引重复建设 (ORACLE没有这个问题,其他都有)

5  语句作废后的无用索引的滞留

3  业务持续变化,SQL语句从简单到复杂,程序员把SQL当程序写,希望一个SQL解决所有需求(这是产生问题的关键)

下面我们用一个SQL和执行计划来说明如何快速的分析一个PG的SQL的优化点。咱们先看语句

这个语句有几个问题

1  语句中使用了数据源嵌套方式,也就是select * from (select * from )我们俗称的子查询,子查询实际上也没有什么问题,关键是子查询中的SQL复杂度和SQL所过滤后的数据量。在子查询中的过滤后的数据量较大的情况下就会产生临时表,SQL过于复杂会增加产生执行计划准确度的难度。所以我们在撰写SQL都希望通过 join的方式来表达表和表之间的关系,并获得关系后的并集,交集等数据结果。

SELECT
  ata.planId,
  ata.detail_di,
  ata.item_di,
  ata.item_code,
  ata.item_name,
  ata.item_pinyin,
  ata.unit_di,
  ata.unit_name,
  ata.enable_muti_size,
  ata.small_class_di,
  ata.small_class_code,
  ata.small_class_name,
  ata.lane_di,
  ata.lane_name,
  ata.standardTime,
  ata.warnTime,
  SUM(ata.maxQty) AS maxQty
FROM
  (
    SELECT
      kifd.itemfilter_di AS planId,
      kifd.detail_di,
      ai.di AS item_di,
      ai.code AS item_code,
      ai.NAME AS item_name,
      ai.pinyin AS item_pinyin,
      ai.unit_di,
      f_get_unit_name (ai.unit_di) AS unit_name,
      ai.enable_muti_size,
      aic2."di" AS small_class_di,
      aic2.code AS small_class_code,
      aic2.NAME AS small_class_name,
      kifd.lane_di,
      kifl.lane_name AS lane_name,
      ki.standard_time AS standardTime,
      ki.warn_time AS warnTime,
      bmcd.maxqty AS maxQty
    FROM
      kc_itemfilter AS kif
      INNER JOIN kc_itemfilter_detail AS kifd ON kif.di = kifd.itemfilter_di
      AND kifd.setting_mode = 0
      LEFT OUTER JOIN kc_itemfilter_lane AS kifl ON kifd.lane_di = kifl.di
      INNER JOIN _item AS ai ON ai.di = kifd.detail_di
      AND ai.delflg = 0
      AND ai.is_enable = TRUE
      AND ai.is_package = FALSE
      AND ai.create__di = '160539'
      INNER JOIN _item_class AS aic2 ON ai.small_class_di = aic2.di
      AND aic2.delflg = 0
      AND aic2.LEVEL = 1
      AND aic2.create__di = '160539'
      LEFT JOIN kc_item AS ki ON ai.di = ki.item_di
      AND ki.item_size_di = -1
      AND ki.delflg = 0
      AND ki.belong__di = '160540'
      LEFT JOIN bm_machine_combine_dishes AS bmcd ON ai.di = bmcd.item_di
      AND bmcd.size_di = -1
      AND bmcd.delflg = 0
      AND bmcd.create__di = ai.create__di
    WHERE
      kifd.itemfilter_di IN ('16053900000000001')
    UNION
    SELECT
      kifd.itemfilter_di AS planId,
      kifd.detail_di,
      ai.di AS item_di,
      ai.code AS item_code,
      ai.NAME AS item_name,
      ai.pinyin AS item_pinyin,
      ai.unit_di,
      f_get_unit_name (ai.unit_di) AS unit_name,
      ai.enable_muti_size,
      aic2."di" AS small_class_di,
      aic2.code AS small_class_code,
      aic2.NAME AS small_class_name,
      kifd.lane_di,
      kifl.lane_name AS lane_name,
      ki.standard_time AS standardTime,
      ki.warn_time AS warnTime,
      bmcd.maxqty AS maxQty
    FROM
      kc_itemfilter AS kif
      INNER JOIN kc_itemlter_detail AS kifd ON kif.di = kifd.itemfilter_di
      AND kifd.setting_mode <> 0
      LEFT OUTER JOIN kc_iteilter_lane AS kifl ON kifd.lane_di = kifl.di
      INNER JOIN _item AS ai ON ai.small_class_di = kifd.detail_di
      AND ai.delflg = 0
      AND ai.is_enable = TRUE
      AND ai.is_package = FALSE
      AND ai.create__di = '160539'
      INNER JOIN _item_lass AS aic2 ON ai.small_class_di = aic2.di
      AND aic2.delflg = 0
      AND aic2.LEVEL = 1
      AND aic2.create__di = '160539'
      LEFT JOIN kc_item AS ki ON ai.di = ki.item_di
      AND ki.item_size_di = -1
      AND ki.delflg = 0
      AND ki.belong__di = '160540'
      LEFT JOIN mach_cobine_dishes AS bmcd ON ai.di = bmcd.item_di
      AND bmcd.size_di = -1
      AND bmcd.delflg = 0
      AND bmcd.create__di = ai.create__di
    WHERE
      kifd.itemfilter_di IN ('16053900000001')
  ) AS ata
GROUP BY
  ata.planId,
  ata.detail_di,
  ata.item_di,
  ata.item_code,
  ata.item_name,
  ata.item_pinyin,
  ata.unit_di,
  ata.unit_name,
  ata.enable_muti_size,
  ata.small_class_di,
  ata.small_class_code,
  ata.small_class_name,
  ata.lane_di,
  ata.lane_name,
  ata.standardTime,
  ata.warnTime
ORDER BY
  small_class_code
QUERY PLAN                                                                                                                                       
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GroupAggregate  (cost=4296.87..4296.98 rows=2 wdith=861) (actual time=2067.727..2068.947 rows=1068 loops=1)
 Group Key:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值