(Oracle)SQL优化案例:组合索引优化

news2024/12/26 14:33:43

项目场景

项目上的ETL模型里有如下SQL语句。执行速度非常慢,每次只查询200条数据,但却需要20多秒的时间。再加上该SQL查询出的数据同步频率很高,这个速度是完全不能忍受的。

因为项目隐私,所以对表及字段做了改写。

SELECT 
IDO.OD_SN
FROM IDO
LEFT JOIN IMO ON IMO.OD_SN= IDO.OD_SN
WHERE IMO.OD_TYPE IN ('X','Y')
AND IMO.SOURCE_ID IS NULL
AND IMO.MODIFY_TIME >= '20240423000000'
AND (IMO.YZ = 'N' OR IDO.YZ = 'N')
AND ROWNUM <= 200

IMO表的数据量:18134780行

IDO表的数据量:2908979行

上述SQL的结果集数量也很明显:200行 

问题分析

上面的SQL对于我等凡人来说,没办法一眼看出哪里有问题;所以还是需要拉一下执行计划(获取执行计划方法文章链接:获取执行计划)。

下面是问题SQL的执行计划,是已经将无关的信息删除。这里是获取的内存中shard_pool的执行计划,是真实的执行计划。

  • Plan hash value: 1275918432
     
    --------------------------------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                     | Name                      | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |
    --------------------------------------------------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT              |                           |      1 |        |       |  2051 (100)|          |    100 |00:00:29.08 |    4057K|      1 |
    |*  1 |  COUNT STOPKEY                |                           |      1 |        |       |            |          |    100 |00:00:29.08 |    4057K|      1 |
    |   2 |   NESTED LOOPS                |                           |      1 |    102 |  6936 |  2051   (1)| 00:00:01 |    100 |00:00:29.08 |    4057K|      1 |
    |   3 |    NESTED LOOPS               |                           |      1 |    102 |  6936 |  2051   (1)| 00:00:01 |    100 |00:00:29.08 |    4056K|      1 |
    |*  4 |     TABLE ACCESS FULL         | IMO                       |      1 |  21724 |   954K|  1846   (1)| 00:00:01 |    100 |00:00:29.08 |    4056K|      0 |
    |*  5 |     INDEX UNIQUE SCAN         | UK_20230901211220_1065023 |    100 |      1 |       |     1   (0)| 00:00:01 |    100 |00:00:00.01 |     202 |      1 |
    |*  6 |    TABLE ACCESS BY INDEX ROWID| IDO                       |    100 |      1 |    23 |     2   (0)| 00:00:01 |    100 |00:00:00.01 |     100 |      0 |
    --------------------------------------------------------------------------------------------------------------------------------------------------------------
     
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       1 - filter(ROWNUM<=100)
       4 - filter(("IMO"."MODIFY_TIME">='20240401000000' AND INTERNAL_FUNCTION("IMO"."OD_TYPE") AND "IMO"."SOURCE_ID" IS NULL))
       5 - access("IMO"."OD_SN"="IDO"."OD_SN")
       6 - filter((DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00279$",5)),NULL,NVL("IMO"."YZ",'N'),'0',NVL("IMO"."YZ",'N'),'1',"IMO"."
                  YZ")='N' OR DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00155$",0)),NULL,NVL("IDO"."YZ",'N'),'0',NVL("IDO"."YZ",'N'),'1'
                  ,"IDO"."YZ")='N'))

从上面的执行计划中,我们可以逐步分析:

  • 连接方式 (id=2、id=3)

IDO表和IMO表的连接方式是 NESTED LOOPS ,因为只返回少量数据(200行),所以走嵌套循环连接完全没问题。

  • 访问路径(id=4)

IMO表的访问路径是TABLE ACCESS FULL;上文已经提过,IMO表有18134780行数据,走全表扫描,还是返回少量数据;走全表扫描肯定是错误的

  • 访问路径(id=6)

IMO表的访问路径是TABLE ACCESS BY INDEX ROWID,索引ROWID扫描,没有问题。

  • 谓词信息

从谓词信息或者SQL语句中,我们可以发现IMO表中的MODIFY_TIME、SOURCE_ID、OD_TYPE字段中发生了谓词过滤。

从上面的信息,我们可以得出以下优化结论了:

Ⅰ:需要让IMO表走索引扫描;

Ⅱ:可以在IMO表上建立MODIFY_TIME、SOURCE_ID、OD_TYPE三个字段的组合索引;其中MODIFY_TIME的选择性最大,OD_TYPE的选择性其次,SOURCE_ID的选择性最差。所以选择MODIFY_TIME作为组合索引的先导列。

优化方案

创建组合索引

CREATE INDEX idx_mtime_type_source ON IMO (MODIFY_TIME,OD_TYPE,SOURCE_ID) ONLINE;

再次执行SQL,发现只需要0.1秒就可以执行完成。

我们此时再来看下执行计划,发现IMO表已经走了索引扫描;组合索引已经起到效果。

Plan hash value: 1019133023
 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name                      | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |                           |      1 |        |       | 19528 (100)|          |    100 |00:00:00.02 |     401 |     49 |
|*  1 |  COUNT STOPKEY                           |                           |      1 |        |       |            |          |    100 |00:00:00.02 |     401 |     49 |
|   2 |   VIEW                                   | VW_ORE_7D109085           |      1 |    103 |  2060 | 19528   (1)| 00:00:01 |    100 |00:00:00.02 |     401 |     49 |
|   3 |    UNION-ALL                             |                           |      1 |        |       |            |          |    100 |00:00:00.02 |     401 |     49 |
|   4 |     NESTED LOOPS                         |                           |      1 |    102 |  6732 |   195   (0)| 00:00:01 |    100 |00:00:00.02 |     401 |     49 |
|*  5 |      TABLE ACCESS BY INDEX ROWID BATCHED | IMO                       |      1 |  21723 |   954K|    93   (0)| 00:00:01 |    100 |00:00:00.01 |     203 |     36 |
|*  6 |       INDEX RANGE SCAN                   | IDX_MTIME_TYPE_SOURCE     |      1 |  21744 |       |     5   (0)| 00:00:01 |    102 |00:00:00.01 |      10 |      9 |
|*  7 |      INDEX UNIQUE SCAN                   | UK_20230901211220_1065023 |    100 |      1 |    21 |     1   (0)| 00:00:01 |    100 |00:00:00.01 |     198 |     13 |
|   8 |     NESTED LOOPS                         |                           |      0 |      1 |    68 | 19332   (1)| 00:00:01 |      0 |00:00:00.01 |       0 |      0 |
|   9 |      NESTED LOOPS                        |                           |      0 |      1 |    68 | 19332   (1)| 00:00:01 |      0 |00:00:00.01 |       0 |      0 |
|* 10 |       TABLE ACCESS BY INDEX ROWID BATCHED| IMO                       |      0 |      1 |    45 | 19330   (1)| 00:00:01 |      0 |00:00:00.01 |       0 |      0 |
|* 11 |        INDEX RANGE SCAN                  | IDX_MTIME_TYPE_SOURCE     |      0 |  21744 |       |   608   (1)| 00:00:01 |      0 |00:00:00.01 |       0 |      0 |
|* 12 |       INDEX UNIQUE SCAN                  | UK_20230901211220_1065023 |      0 |      1 |       |     1   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |      0 |
|* 13 |      TABLE ACCESS BY INDEX ROWID         | IDO                       |      0 |      1 |    23 |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |      0 |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(ROWNUM<=100)
   5 - filter(DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00279$",5)),NULL,NVL("IMO"."YZ",'N'),'0',NVL("IMO"."YZ",'N'),'1',"IMO"."YZ
              ")='N')
   6 - access("IMO"."MODIFY_TIME">='20240401000000' AND "IMO"."SOURCE_ID" IS NULL AND "IMO"."MODIFY_TIME" IS NOT NULL)
       filter((INTERNAL_FUNCTION("IMO"."OD_TYPE") AND "IMO"."SOURCE_ID" IS NULL))
   7 - access("IMO"."OD_SN"="IDO"."OD_SN")
  10 - filter(LNNVL(DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00279$",5)),NULL,NVL("IMO"."YZ",'N'),'0',NVL("IMO"."YZ",'N'),'1',"IMO"."YZ
              ")='N'))
  11 - access("IMO"."MODIFY_TIME">='20240401000000' AND "IMO"."SOURCE_ID" IS NULL AND "IMO"."MODIFY_TIME" IS NOT NULL)
       filter((INTERNAL_FUNCTION("IMO"."OD_TYPE") AND "IMO"."SOURCE_ID" IS NULL))
  12 - access("IMO"."OD_SN"="IDO"."OD_SN")
  13 - filter(DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00155$",0)),NULL,NVL("IDO"."YZ",'N'),'0',NVL("IDO"."YZ",'N'),'1',"IDO"."YZ
              ")='N')

 

 

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

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

相关文章

嵌入式Linux八股(三)——计算机基础

三、计算机基础 01.操作系统 01.进程几种状态 02.锁 互斥锁&#xff1a;互斥锁是一种用于线程同步的工具&#xff0c;能够保证同一时刻只有一个线程可以访问共享资源。如果一个线程已经取得了互斥锁&#xff0c;其他尝试获得该锁的线程将会被阻塞&#xff0c;直到第一个线程…

基于springboot+vue的游艇停泊系统

一、系统架构 前端&#xff1a;vue2 | element-ui |html 后端&#xff1a;springboot | mybatis-plus 环境&#xff1a;jdk1.8 | mysql | maven | node 二、代码及数据库 三、功能介绍 01. web端-登录 02. web端-系统首页1 03. web端-系统首页2 04. web端-泊位 05. web…

【南京工程学院×朗汀留学】部分录取案例合集

朗汀留学 X 南京工程学院 作为深耕留学的专业资深团队&#xff0c;朗汀留学成功帮助上千名学生出国留学。 在此我们将南京工程学院的部分留学案例作以总结&#xff0c;以供新生参考。再次恭喜所有 获得理想大学offer的学生们&#xff0c;你们的努力让梦想照进现实。 学校介绍…

linux下编译c++程序报错“undefined reference to `std::allocator<char>::allocator()‘”

问题 linux下编译c程序报错“undefined reference to std::allocator::allocator()”。 原因 找不到c标准库文件。 解决办法 开始尝试给gcc指令添加-L和-l选项指定库路径和库文件名&#xff0c;但是一直不成功&#xff0c;后来把gcc改为g就可以了。

关于路由过滤、路由策略的实验eNSP

具体接口IP地址如下图所示 第一步&#xff1a;配置IP R1: [R1]int g 0/0/0 [R1-GigabitEthernet0/0/0]ip ad [R1-GigabitEthernet0/0/0]ip address 100.1.1.1 24 Apr 23 2024 19:35:38-08:00 R1 %%01IFNET/4/LINK_STATE(l)[0]:The line protocol IP on the interface Giga…

智能AI伪原创,高效率一键生成优质文章

如今&#xff0c;内容创作已经成为许多企业和个人关注的焦点。然而&#xff0c;随着信息量的不断增加&#xff0c;想要在短时间内创作出优质的文章成为了一个挑战。但随着人工智能技术的飞速发展&#xff0c;智能AI伪原创的出现&#xff0c;为我们提供了一种全新的解决方案。这…

TensorRT plugins and ONNX parser编译

https://github.com/NVIDIA/TensorRT是TensorRT plugins and ONNX parser&#xff0c;并不包含TensorRT的nvinfer库&#xff08;libinfer.so、nvinfer.dll&#xff09;&#xff0c;此部分并未开源&#xff0c;只能使用官方支持的平台、环境https://developer.nvidia.com/tensor…

【打工日常】云原生之使用Docker部署开源云笔记工具Leanote

一、Leanote蚂蚁笔记介绍 1.Leanote简介 Leanote 蚂蚁笔记是一款国产开源的私有云笔记工具。它支持普通格式笔记、Markdown语法、专业数学公式编辑、和思维导图&#xff0c;并且支持vim&emacs等编辑模式。 2.Leanote功能 拥有Markdown 语法支持、无干扰写作模式、Vim和Ema…

值传递和地址传递

文章目录 目录值传递地址传递 目录 值传递 package com.zhang.parameter; //值传递 public class MethodDemo1 {public static void main(String[] args) {int a 10;System.out.println(a);System.out.println("~~~~~~~~~~~~~~~");change(a);//无论你传入的是什么 …

el-select下拉框远程搜索且多选时,编辑需要回显的一个简单案例

前端业务开发中不管使用vue2~3&#xff0c;还是react&#xff0c;angular各种前端技术栈&#xff0c;经常会遇到这种业务。一个下拉框Select中&#xff0c;不仅需要需要支持远程模糊搜索&#xff0c;还需要支持多选。并且在编辑时&#xff0c;还能正常把已经多选好的内容回显到…

租房管理|基于SprinBoot+vue的租房管理系统(源码+数据库+文档)

租房管理目录 基于SprinBootvue的租房管理系统 一、前言 二、系统设计 三、系统功能设计 前台 后台 管理员 订单信息管理 屋主申诉管理 屋主权限 房源信息管理 订单信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获…

微信小程序开发工具的使用,各个配置文件详解,小程序开发快速入门

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

wfs 文件存储系统 v1.0.5

前言&#xff1a;wfs 是高性能海量小文件存储系统 &#xff0c;支持Linux&#xff0c;Windows&#xff0c;Macos&#xff0c;FreeBSD等系统&#xff0c; 可以高效地进行文件存储和读取。wfs 支持文件压缩归档&#xff0c;并提供简洁的数据读取方式和文件后台管理和 以及归档文件…

STM32学习和实践笔记(14):按键控制实验

消除抖动有软件和硬件两种方法 软件方法就是在首次检测到低电平时加延时&#xff0c;通常延时5-10ms&#xff0c;让抖动先过去&#xff0c;然后再来检测是否仍为低电平&#xff0c;如果仍然是&#xff0c;说明确实按下。 硬件方法就是加RC滤波电路&#xff0c;硬件方法会增加…

SystemUI GlobalActions plugin解析

com.android.systemui.action.PLUGIN_GLOBAL_ACTIONS 系统的默认实现为GlobalActionsImpl: 是谁发送了showShutdownUi指令&#xff1f; GlobalActionsImpl 是通过inject的方式创建的 GlobalActionsComponent是一个system UI services&#xff0c;配置在config.xml中&#xff…

架构师系列-Nginx、OpenResty(一)- 基本使用配置

Nginx 模块 高度模块化的设计是 Nginx 的架构基础&#xff0c;Nginx 服务器被分解为多个模块&#xff0c;每个模块就是一个功能模块&#xff0c;只负责自身的功能&#xff0c;模块之间严格遵循“高内聚&#xff0c;低耦合”的原则。 核心模块 核心模块是 Nginx 服务器正常运行…

vue2项目升级到vue3经历分享

依据vue官方文档&#xff0c;vue2在2023年12月31日终止维护。因此决定将原来的岁月云记账升级到vue3&#xff0c;预计工作量有点大&#xff0c;于是想着把过程记录下来。 原系统使用的技术栈 "dependencies": {"axios": "^0.21.1","babel-…

博士困境::博士毕业出路何在

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

Windows 搭建自己的大模型-通义千问

1、安装 pytorch https://pytorch.org/get-started/locally/ 点击进入官网&#xff0c;如图选择自己的环境得到pip安装依赖的命令&#xff1a; pip3 install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cpu 2、拉取代码并安…

欢乐钓鱼大师一键钓鱼,解放双手!

《钓鱼欢乐大师》是一款让玩家体验钓鱼乐趣的游戏&#xff0c;在游戏中&#xff0c;玩家可以通过技巧和策略钓到各种各样的鱼。为了提高钓鱼效率&#xff0c;让玩家更快地钓到大鱼&#xff0c;下面将介绍如何利用脚本来优化游戏体验。 第一步&#xff1a;准备工作 创建云机&…