当MogDB遇到标量子查询中有limit或rownum怎么办

在过去的一些项目中,我们发现对于标量子查询带limit或者rownum的情况下,Oracle的性能非常高效,而MogDB的性能似乎差强人意,那么如果在使用MogDB的过程中遇到了这样的场景,该如何进行优化呢?

这里我们来给大家分享一些优化方法。

首先来看看Oracle的情况

这里我们先模拟构造一些数据,用来测试验证.


create table test02 as select * from dba_objects;
create table test01 as select * from test02;
insert into test01 select * from test01;
insert into test01 select * from test01;
insert into test01 select * from test01;
commit;
insert into test01 select * from test01;
insert into test01 select * from test01;
insert into test01 select * from test01;
commit;
insert into test01 select * from test01;
insert into test01 select * from test01;
insert into test01 select * from test01;
commit;
create index idx_test01_owner on test01(owner);


数据构造完毕之后,我们来看看Oracle 11g中该测试SQL的执行计划如何。

SQL> select count(1) from test01;

  COUNT(1)
----------
  22858240

Elapsed: 00:00:03.75
SQL> select count(1) from test02;

  COUNT(1)
----------
     89290

Elapsed: 00:00:00.07
SQL> 
SQL> SELECT object_id, t1.owner,
  2    (SELECT t2.object_name
  3     FROM test01 t2
  4     WHERE t1.owner = t2.owner
  5       AND rownum <= 1)
  6  FROM test02 t1
  7  WHERE rownum <= 10;

 OBJECT_ID OWNER                          (SELECTT2.OBJECT_NAMEFROMTEST01T2WHERET1.OWNER=T2.OWNERANDRO
---------- ------------------------------ ------------------------------------------------------------
        20 SYS                            ICOL$
        46 SYS                            ICOL$
        28 SYS                            ICOL$
        15 SYS                            ICOL$
        29 SYS                            ICOL$
         3 SYS                            ICOL$
        25 SYS                            ICOL$
        41 SYS                            ICOL$
        54 SYS                            ICOL$
        40 SYS                            ICOL$

10 rows selected.

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1781923309

-------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                  |    10 |   300 |     2   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY               |                  |       |       |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| TEST01           |   250K|    19M|     4   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | IDX_TEST01_OWNER |   100K|       |     3   (0)| 00:00:01 |
|*  4 |  COUNT STOPKEY               |                  |       |       |            |          |
|   5 |   TABLE ACCESS FULL          | TEST02           | 81940 |  2400K|     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(ROWNUM<=1)
   3 - access("T2"."OWNER"=:B1)
   4 - filter(ROWNUM<=10)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          9  consistent gets
         12  physical reads
          0  redo size
        862  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         10  rows processed

SQL> 

可以看到,在Oracle 中该SQL执行效率非常高效,毫秒级返回结果。然后在早期的MogDB版本中,处理该SQL性能并不高高效,会走bitmap index scan。

首先我们通过mtk迁移工具将该2个表测试数据迁移到mogdb中,然后测试验证一把。

至于迁移步骤,这里我就不在提了,大家可以参考之前的文章。

MogDB 验证

这里我使用了MogDB 5.0.5版本。废话不多说,直接上测试过程。

[omm@mogdb1 ~]$ gsql -r -d test -Uroger
Password for user roger: 
gsql ((MogDB 5.0.5 build b77f1a82) compiled at 2023-12-08 03:11:47 commit 0 last mr 1804 )
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type "help" for help.

test=> \timing on
Timing is on.
test=> 
test=>    SELECT object_id, t1.owner,
test->   (SELECT t2.object_name
test(>    FROM test01 t2
test(>    WHERE t1.owner = t2.owner
test(>      AND rownum <= 1)
test-> FROM test02 t1
test-> WHERE rownum <= 10;
 object_id | owner | object_name 
-----------+-------+-------------
        20 | SYS   | ICOL$
        46 | SYS   | ICOL$
        28 | SYS   | ICOL$
        15 | SYS   | ICOL$
        29 | SYS   | ICOL$
         3 | SYS   | ICOL$
        25 | SYS   | ICOL$
        41 | SYS   | ICOL$
        54 | SYS   | ICOL$
        40 | SYS   | ICOL$
(10 rows)

Time: 18472.299 ms
test=> 
test=>  explain 
test-> SELECT object_id, t1.owner,
test->   (SELECT t2.object_name
test(>    FROM test01 t2
test(>    WHERE t1.owner = t2.owner
test(>      AND rownum <= 1)
test-> FROM test02 t1
test-> WHERE rownum <= 10;
                                                 QUERY PLAN                                                 
------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.00..179830.95 rows=10 width=11)
   ->  Seq Scan on test02 t1  (cost=0.00..1605908407.74 rows=89301 width=11)
         SubPlan 1
           ->  Limit  (cost=17982.47..17983.07 rows=1 width=24)
                 ->  Bitmap Heap Scan on test01 t2  (cost=17982.47..591299.40 rows=952544 width=24)
                       Recheck Cond: ((t1.owner)::text = (owner)::text)
                       ->  Bitmap Index Scan on idx_test01_owner  (cost=0.00..17744.33 rows=952544 width=0)
                             Index Cond: ((t1.owner)::text = (owner)::text)
(8 rows)

Time: 1.544 ms
test=> 
test=> select t2.object_name from test01 t2 where 'SYS' = t2.owner and rownum <= 1;
 object_name 
-------------
 ICOL$
(1 row)

Time: 1.496 ms
test=> explain select t2.object_name from test01 t2 where 'SYS' = t2.owner and rownum <= 1;
                                QUERY PLAN                                 
---------------------------------------------------------------------------
 Limit  (cost=0.00..0.07 rows=1 width=24)
   ->  Seq Scan on test01 t2  (cost=0.00..687643.20 rows=9726617 width=24)
         Filter: ('SYS'::text = (owner)::text)
(3 rows)

Time: 1.292 ms
test=> 


从第一次执行的情况来看,该SQL需要10多秒,简直是比Oracle慢太多了,无法仍受。实际上我们分析上述的执行计划可以看到,主要慢在了bitmap scan上了。

这里我们暂时用hint禁用该功能。

test=> SELECT /*+ set(enable_bitmapscan off) */ object_id, t1.owner,
test->   (SELECT t2.object_name
test(>    FROM test01 t2
test(>    WHERE t1.owner = t2.owner
test(>      AND rownum <= 1)
test-> FROM test02 t1
test-> WHERE rownum <= 10;
 object_id | owner | object_name 
-----------+-------+-------------
        20 | SYS   | ICOL$
        46 | SYS   | ICOL$
        28 | SYS   | ICOL$
        15 | SYS   | ICOL$
        29 | SYS   | ICOL$
         3 | SYS   | ICOL$
        25 | SYS   | ICOL$
        41 | SYS   | ICOL$
        54 | SYS   | ICOL$
        40 | SYS   | ICOL$
(10 rows)

Time: 3.367 ms
test=> explain SELECT /*+ set(enable_bitmapscan off) */ object_id, t1.owner,
test->   (SELECT t2.object_name
test(>    FROM test01 t2
test(>    WHERE t1.owner = t2.owner
test(>      AND rownum <= 1)
test-> FROM test02 t1
test-> WHERE rownum <= 10;
                                       QUERY PLAN                                       
----------------------------------------------------------------------------------------
 Limit  (cost=0.00..7.49 rows=10 width=11)
   ->  Seq Scan on test02 t1  (cost=0.00..66929.56 rows=89301 width=11)
         SubPlan 1
           ->  Limit  (cost=0.00..0.72 rows=1 width=24)
                 ->  Seq Scan on test01 t2  (cost=0.00..687643.20 rows=952544 width=24)
                       Filter: ((t1.owner)::text = (owner)::text)
(6 rows)

Time: 1.467 ms
test=> 

我们可以看到此时执行计划正常了,快如闪电了。

在6月30号即将发布的新版本中SQL引擎就具备该能力,不再需要人工干预了。

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/799779.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

光伏EPC项目管理系统的综合性管理理念和功能优势。

光伏EPC项目管理系统是一种适用于工程项目的管理软件&#xff0c;它强调在整个项目周期中的综合性管理理念&#xff0c;涵盖了从规划、设计、采购、施工到交付等全过程&#xff0c;帮助用户实现高效的项目管理。 1.增强项目团队之间的协作与沟通&#xff1a;光伏EPC项目管理系统…

【二分查找】Leetcode 搜索插入位置

题目解析 35. 搜索插入位置 这道题就是寻找target的目标位置&#xff0c;如果nums中包含target直接返回索引&#xff1b;如果不包含&#xff0c;需要返回target存放的合适位置 注意这道题有一个细节地方需要注意&#xff1a;如果现在target没有在nums中出现&#xff0c;并且目…

Electron 打包自定义NSIS脚本为安装向导增加自定义页面增加输入框

Electron 打包工具有很多&#xff0c;如Electron-build、 Electron Forge 等&#xff0c;这里使用Electron-build&#xff0c;而Electron-build使用了nsis组件来创建安装向导&#xff0c;默认情况nsis安装向导不能自定义安装向导界面&#xff0c;但是nsis提供了nsis脚本可以扩展…

ESP32调试笔记

目录 基于Thonny和micropythonESP32-CAM开发板无法连接Thonnyesp32cam局域网图传esp32代码上位机代码 基于Thonny和micropython ESP32-CAM开发板无法连接Thonny esp32cam有两个模式&#xff1a;下载模式、运行模式 两种模式的接线不同 IO0 短路 GND ! 正是因为两种模式接线…

Cloak斗篷技术:FP独立站的隐身术

FP商家常常面临着一个难题&#xff1a;如何在满足各大主流平台如Facebook、Google、TikTok等严格审核的同时&#xff0c;又能向买家展示真正想要推广的商品内容&#xff1f; Cloak斗篷技术正是为解决这一难题而诞生的。 简而言之&#xff0c;Cloak斗篷技术就如同给网页穿上了一…

[AI in sec]-039 DNS隐蔽信道的检测-特征构建

DNS隐蔽信道是什么 DCC是指利用DNS数据包中的可定义字段秘密传递信息的通道。其中,“DNS 协议”是目前网络上使用的标准域名解析协议;“可定义字段”是DNS 数据包中的 QNAME 字段、RDATA 字段及RawUDP字段。利用DNS数据包可以构建2种信道:存储信道及时间信道。DCC可以被用于…

nginx配置实例-动静分离

目录 一、相关概念 1.1动静分离概念 1.2动静分离的两种实现方法 二、实例配置 2.1 准备工作&#xff1a;在linux系统中准备静态资源&#xff0c;方便后面做测试 2.2 修改nginx配置文件 2.3 在浏览器测试 一、相关概念 1.1动静分离概念 将动态请求跟静态请求分开&#xf…

大模型在金融行业的应用场景和落地路径

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…

李沐20_卷积层里的填充和步幅——自学笔记

填充和步幅 给定32✖32的输入图像&#xff0c;应用5✖5大小的卷积核&#xff08;第一层输出28✖28&#xff0c;第7层输出大小是4✖4&#xff0c;即每一层都-4&#xff09; 更大的卷积核可以更快地减小输出大小&#xff1a;形状从nk✖nk减少到(nh-kn1)✖(nw-kw1) 1.填充 在输…

理解 Golang 变量在内存分配中的规则

为什么有些变量在堆中分配、有些却在栈中分配&#xff1f; 我们先看来栈和堆的特点&#xff1a; 简单总结就是&#xff1a; 栈&#xff1a;函数局部变量&#xff0c;小数据 堆&#xff1a;大的局部变量&#xff0c;函数内部产生逃逸的变量&#xff0c;动态分配的数据&#x…

VueRouter的介绍:什么是路由呢?VueRouter的作用及使用,VueRouter的使用分为5个步骤和特定的2步

1.什么是路由呢&#xff1f; 路由就是路径和组件之间的映射关系&#xff0c;当我们路径变化的时候&#xff0c;就要切换对应的组件。 在前端中解决路径与组件之间的映射关系&#xff0c;官方提供了VueRouter这个插件 2.VueRouter的作用及使用 作用&#xff1a;修改地址栏路…

ios苹果ipa文件app内测分发有哪些操作流程

哈喽&#xff0c;大家好&#xff0c;咕噜淼淼又来和大家见面啦&#xff0c;在iOS应用开发过程中&#xff0c;进行内测分发是非常重要的一环&#xff0c;它能帮助开发者发现并修复应用中的问题&#xff0c;提升用户体验。上两期咱们一起探讨了一下App内测分发的目的及优势&#…

【计算机考研】408有多难?复习到什么程度才能120+?

备考计算机考研的408统考是一件需要花费精力和时间的事情&#xff0c;我想分享一些基于个人经验的备考策略&#xff0c;希望能帮助到大家。 首先&#xff0c;我将备考过程划分为三轮进行。在第一轮复习阶段&#xff0c;我每天安排3小时的时间学习机组原理和操作系统&#xff0…

Android Binder——ServiceManager初始化(六)

上一篇文章介绍到 servicemanager 的 main 函数中主要做了四件事: 1)初始化 binder 驱动。 2)将自身以“manager”添加到 servicemanager 中的 map 集合中。 3)注册成为 binder 驱动的上下问管理者。 4)给 Looper 设置 callback,进入无限循环,处理 client 端发来的请求。…

Linux 函数学习

1、Linux poll 函数 int poll(struct pollfd *fds, nfds_t nfds, int timeout); fds&#xff1a; 需要轮询的fd集合 nfds&#xff1a;需要轮询的fds数量 timeout&#xff1a;超时时间 返回值&#xff1a;0 超时&#xff0c;<0 发生异常&#xff0c;> 0 存在数据变化 …

【LeetCode热题100】153. 寻找旋转排序数组中的最小值(二分)

一.题目要求 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,2]若旋转 7…

几行代码搞懂静态类和静态方法

视频链接: 视频 代码链接: 源码 在C#中&#xff0c;静态类&#xff08;Static Class&#xff09;和静态方法&#xff08;Static Method&#xff09;是面向对象编程中的重要概念。它们允许你创建不依赖于对象实例的方法和属性&#xff0c;而是直接通过类名来访问。 静态类 静…

python学习笔记——类

1. 类和对象**** 类、类属性、类方法不需要实例化就可以直接访问 实例相关&#xff0c;如实例属性、实例方法必须实例化后才可以访问 1.1. 类、类属性、实例属性、私有属性**** 1.1.1. 定义**** 类就是拥有相同属性和功能对象的集合 动物&#xff1a;猫、狗、鸡 人类&…

【AIGC调研系列】AI大模型结合迁移学习进行微调的应用

AI大模型结合迁移学习进行微调的应用主要体现在通过预训练模型快速适应新任务&#xff0c;提高模型性能和准确性。迁移学习允许我们利用在其他任务上学到的知识来加速新任务的学习过程&#xff0c;从而减少对大量标注数据的依赖&#xff0c;提高训练效率[1][2][3]。在AI领域&am…

Python mixin

Python 中的 Mixin 类是一种特殊的继承机制,它允许我们在不修改类层次结构的情况下,向一个类添加额外的功能。Mixin 类通常包含一些可复用的方法或属性,可以被其他类继承和使用。 Mixin 类的主要特点如下: 可复用性: Mixin 类包含可重用的方法或属性,可以被多个类继承和使用,提…