首页 > 数据库 >KingabseES-SQL优化_提升子查询

KingabseES-SQL优化_提升子查询

时间:2022-12-13 19:14:55浏览次数:42  
标签:KingabseES t01id cost .. 查询 width rows t02 SQL

什么是提升子查询/子链接

SubLink,子查询/子链接,他们的区别:子查询不在表达式中子句,子链接在in/exists表达式中的子句。

  • 若以范围表的方式存在,则是子查询;
  • 若以表达式的存在,则是子连接;
  • 出现在FROM关键字后的子句是子查询语句,出现在where/on等约束条件或者投影中的子句是子连接

提升子链接,尝试将ANY和EXISTS子链接作为半联接或反半联接处理。

下面情况,不能实现提升。

  • 子连接右操作数:不能出现包含上层任何Var对象
  • 子连接左操作数:
    • 一定与上层出现的Var结构体表示的对象有相同,如果没有,可以直接求解,不用和上层关联
    • 不能引用上层出现的关系
    • 不能出现易失函数

提升子查询

简单子查询的提升:
select * from t01 as a, (select * from t02) as b where a.id = b.t01id and a.c1 = 100;
转化为:
select * from t01 as a, t02 as b where a.id = b.t01id and a.c1 = 100;

explain
select *
from t01 as a,
      (select * from t02) as b
where a.id = b.t01id
  and a.c1 = 100;

                               QUERY PLAN
-----------------------------------------------------------------------------------
Nested Loop  (cost=9.55..3118.70 rows=899 width=55)
  ->  Bitmap Heap Scan on t01 a  (cost=4.35..32.11 rows=9 width=41)
        Recheck Cond: (c1 = 100)
        ->  Bitmap Index Scan on idx_t01_c1  (cost=0.00..4.35 rows=9 width=0)
              Index Cond: (c1 = 100)
  ->  Bitmap Heap Scan on t02  (cost=5.20..341.95 rows=100 width=14)
        Recheck Cond: (t01id = a.id)
        ->  Bitmap Index Scan on idx_t02_t01id  (cost=0.00..5.17 rows=100 width=0)
              Index Cond: (t01id = a.id)

子查询含有集合操作、聚合操作、sort/limit/with/group, 当关键列的过滤条件使用常量,可以支持提升。

explain
select *
from t01 as a,
     (select t01id, count(*) tups from t02 group by t01id) as b
where a.id = b.t01id
  and a.id = 100;
                               QUERY PLAN
-----------------------------------------------------------------------------------
Nested Loop  (cost=0.71..17.98 rows=100 width=53)
  ->  Index Scan using t01_pkey on t01 a  (cost=0.29..8.30 rows=1 width=41)
        Index Cond: (id = 100)
  ->  GroupAggregate  (cost=0.42..7.67 rows=100 width=12)
        Group Key: t02.t01id
        ->  Index Only Scan using idx_t02_t01id on t02  (cost=0.42..6.17 rows=100 width=4)
              Index Cond: (t01id = 100)

并不是所有的子查询都能提升,含有集合操作、聚合操作、sort/limit/with/group、易失函数、from为空等,关键列的过滤条件使用非常量,是不支持提升的。 如下:

explain
select *
from t01 as a,
     (select t01id, count(*) tups from t02 group by t01id) as b
where a.id = b.t01id
  and a.c1 = 100;
                               QUERY PLAN
-----------------------------------------------------------------------------------
Hash Join  (cost=20467.23..20693.85 rows=9 width=53)
  Hash Cond: (t02.t01id = a.id)
  ->  HashAggregate  (cost=20435.00..20535.16 rows=10016 width=12)
        Group Key: t02.t01id
        ->  Seq Scan on t02  (cost=0.00..15435.00 rows=1000000 width=4)
  ->  Hash  (cost=32.11..32.11 rows=9 width=41)
        ->  Bitmap Heap Scan on t01 a  (cost=4.35..32.11 rows=9 width=41)
              Recheck Cond: (c1 = 100)
              ->  Bitmap Index Scan on idx_t01_c1  (cost=0.00..4.35 rows=9 width=0)
                    Index Cond: (c1 = 100)

SQL改写

子查询含有集合操作、聚合操作、sort/limit/with/group、易失函数、from为空等,关键列的过滤条件使用非常量,通过SQL改写,实现提升子查询。

lateral改写

lateral关键字,可以将关联条件,写入子查询中,让子查询可以循环执行。

explain
select *
from t01 as a,
    lateral (select t01id, count(*) tups, sum(b.v1) v1 from t02 as b where a.id = b.t01id group by t01id)
where a.c1 = 100;
                               QUERY PLAN
-----------------------------------------------------------------------------------
Nested Loop  (cost=9.56..3390.67 rows=900 width=85)
  ->  Bitmap Heap Scan on t01 a  (cost=4.35..32.11 rows=9 width=41)
        Recheck Cond: (c1 = 100)
        ->  Bitmap Index Scan on idx_t01_c1  (cost=0.00..4.35 rows=9 width=0)
              Index Cond: (c1 = 100)
  ->  GroupAggregate  (cost=5.21..371.17 rows=100 width=44)
        Group Key: b.t01id
        ->  Bitmap Heap Scan on t02 b  (cost=5.21..369.17 rows=101 width=10)
              Recheck Cond: (a.id = t01id)
              ->  Bitmap Index Scan on idx_t02_t01id  (cost=0.00..5.18 rows=101 width=0)
                    Index Cond: (t01id = a.id)


any(array())改写

使用any和array将关联条件,转化为稳定函数

explain
with a as (select *
           from t01 as a
           where a.c1 = 100)
select *
from a,
     (select t01id, count(*) tups, sum(b.v1) v1 from t02 group by t01id) as b
where a.id = b.t01id
and  b.t01id = any (array (select id from a)) ;
                               QUERY PLAN
-----------------------------------------------------------------------------------
Hash Join  (cost=2659.27..2684.79 rows=43 width=84)
  Hash Cond: (t02.t01id = a.id)
  CTE a
    ->  Bitmap Heap Scan on t01 a_1  (cost=4.35..32.11 rows=9 width=41)
          Recheck Cond: (c1 = 100)
          ->  Bitmap Index Scan on idx_t01_c1  (cost=0.00..4.35 rows=9 width=0)
                Index Cond: (c1 = 100)
  InitPlan 2 (returns $1)
    ->  CTE Scan on a a_2  (cost=0.00..0.18 rows=9 width=4)
  ->  HashAggregate  (cost=2626.68..2638.63 rows=956 width=44)
        Group Key: t02.t01id
        ->  Bitmap Heap Scan on t02  (cost=52.08..2619.15 rows=1005 width=10)
              Recheck Cond: (t01id = ANY ($1))
              ->  Bitmap Index Scan on idx_t02_t01id  (cost=0.00..51.83 rows=1005 width=0)
                    Index Cond: (t01id = ANY ($1))
  ->  Hash  (cost=0.18..0.18 rows=9 width=40)
        ->  CTE Scan on a  (cost=0.00..0.18 rows=9 width=40)


子查询嵌入关联表

为了便于查询语句的共享与功能扩展,可以将关联表嵌入子查询,并使用新的子查询脚本,创建公用视图。

create view v_0102 as
select (a).*, tups
      from (select a, count(*) tups,sum(v1) v1
            from t02 b
                     join t01 a on b.t01id = a.id
            group by b.t01id, a);
            
explain
select *
from v_0102
where c1 = 100;
                               QUERY PLAN
-----------------------------------------------------------------------------------
Subquery Scan on t  (cost=141.10..168.10 rows=900 width=48)
  ->  GroupAggregate  (cost=141.10..159.10 rows=900 width=109)
        Group Key: b.t01id, a.*
        ->  Sort  (cost=141.10..143.35 rows=900 width=69)
              Sort Key: b.t01id, a.*
              ->  Nested Loop  (cost=4.78..96.94 rows=900 width=69)
                    ->  Bitmap Heap Scan on t01 a  (cost=4.35..32.11 rows=9 width=69)
                          Recheck Cond: (c1 = 1000)
                          ->  Bitmap Index Scan on idx_t01_c1  (cost=0.00..4.35 rows=9 width=0)
                                Index Cond: (c1 = 1000)
                    ->  Index Only Scan using idx_t02_t01id on t02 b  (cost=0.42..6.19 rows=101 width=4)
                          Index Cond: (t01id = a.id)


总结

应用程序通过 SQL 语句来操作数据库时会使用大量的子查询,这种写法比直接对两个表做连接操作在结构上和思路上更清晰,尤其是在一些比较复杂的查询语句中,子查询有更完整、更独立的语义,会使 SQL 对业务逻辑的表达更清晰更容易理解,因此得到了广泛的应用。

  • 子查询 SubQuery:对应于查询解析树中的范围表,更通俗一些指的是出现在 FROM/JOIN 语句后面的独立的 SELECT 语句。
  • 子链接 SubLink:对应于查询解析树中的表达式,更通俗一些指的是出现在 where/on 子句、selectlist 里面的语句。

综上,对于查询解析树而言,SubQuery 的本质是范围表,而 SubLink 的本质是表达式。

其中分析系统和事务分析混合系统场景中,常用的 sublink 为 exist_sublink、any_sublink,在 Kingbase的优化引擎中对其应用场景做了优化(子链接提升),由于 SQL 语句中子查询的使用的灵活性,会带来 SQL 子查询过于复杂造成性能问题 。

复杂SQL子查询,通过SQL改写,可以转化为子链接,实现提升子链接。提升后的子链接,虽然可以提升在少量数据的性能,但随着数据量的增加,执行时长就会大幅度超过HASH JOIN全量数据。

标签:KingabseES,t01id,cost,..,查询,width,rows,t02,SQL
From: https://www.cnblogs.com/kingbase/p/16945452.html

相关文章

  • Sql Server 2008R2升级Sql Server 2012图文教程
    原文链接:https://www.jb51.net/article/126558.htm环境:Windowsserver2008r2Standard+SqlServer2008R2内网环境需要升级为SQLserver2012升级安装时提示版本不支......
  • SQL_5_多行函数
    通过groudby语句可以给结果集进行分组。函数是处理查询结果的方法。组函数(多行函数):对结果集的每一组都进行运算,得到一个值。(除了空值,若要处理组中的空值可以使用nvl......
  • java springboot项目树结构递归查询
    记录工作本文记录树结构递归查询,像菜单栏和部门首先需要一张表CREATETABLE`sys_dict`(`id`intNOTNULLAUTO_INCREMENT,`parent_id`intNOTNULL,`name`......
  • SQLite: 多行合并字符串、字串转多行
    网络收集整理如下: CREATETABLEt_email(email_idINTEGERPRIMARYKEYAUTOINCREMENT,schedule_idINTEGER,line_idINTEGER,mail_gro......
  • 北京智和信通:交换机策略查询与自动化配置
     在网络中交换机占据重要位置,一旦交换机被攻击或破坏,都将使整个网络处于危险之中。在网络的日常配置管理中,交换机的配置也是核心工作,但在交换机的配置过程复杂,而且根据品......
  • postgresql 时间格式 获取年初年末年末 ,月初月末日期,本日,去年等日期
      --获取本天yyyy-MM-dd/2022-12-13selectcurrent_date;--获取本天date/2022-12-13selectnow();--获取本天/13selectdate_part('day',curre......
  • Mysql - 多源复制
    一、说明我们使用mysql大多数都是一主一从或者是一主多从的架构,但在有些情况下我们希望能将多个主库同步到一个从库下面,本文将介绍多主一从的安装方法以及注意事项。实验......
  • SQLIte的安装及库创建
    1.SQLite官方下载地址:https://www.sqlite.org/download.html,下载完成后,将压缩包解压到同一文件夹下 2.CMD命令符切换到上面文件夹,运行sqlite3,显示SQLite版本即表示安装......
  • SQLyog安装和使用
    百度搜索下载安装链接:https://pan.baidu.com/s/1FSZgtDoMWE5Is9Gu_xpjhg提取码:ABAP下载解压后打开.exe可执行文件  选择自己想要的语言,下一步即可然后打开SQLyog......
  • win101-Windows环境下MYSQL5.7免安装版下载、配置(win10-x64位32g内存)
     win101-Windows环境下MYSQL5.7免安装版下载、配置(win10-x64位32g内存)一、MYSQL免安装版下载二、解压安装三、设置登录、修改密码一、MYSQL免安装版下载1、下载链接......