SQL使用复合索引实现数据库查询的优化


Posted in SQL Server onMay 25, 2022

一 问题

程序再在一次查询时出现查询时间过长,每次查询要1-2分钟业务反馈用户操作体验很差,sql如下:

select *
FROM edi_booking edibooking0_
WHERE 1 = 1
        AND edibooking0_.load_port_code IN ('CNCWN', 'CNDCB', 'AA', 'CNMWN'
        , 'CWHSD', 'CNSHK', 'CNYTN', 'CNSKU')
        AND edibooking0_.carrier_code = 'WHL'
        AND upper(edibooking0_.so_no) LIKE upper('025%')
        AND edibooking0_.load_port_code = 'CNSHK'
        AND edibooking0_.status <= 1
        AND edibooking0_.tfc_code = 'E19957'
ORDER BY edibooking0_.so_no ASC;

需要对查询进行优化。

二 分析

还是老样子,先看看执行计划,看看走没走索引,不查不知道一查吓一跳,执行计划上居然显示走了索引,索引是函数索引upper(so_no) ,走了索引为什么还慢呢,根据以往的经验,走了索引不是应该很快才对吗?奇奇怪怪,于是注意到了查询条件中还有一个条件tfc_code,又发现这个字段其实也有建立索引,是不是数据库的执行计划有问题,没有走tfc_code索引呢?或者说tfc_code索引本身有问题,于是进行重建tfc_code索引

alter index EDI_BOOKING_IDX_TFC_CODE rebuild online;

执行后,哇塞,查询速度果然上来了,2s钟返回查询结果。查看执行计划,走了tfc_code索引,nice! 但是故事还没有结束! 过了一天后,业务又反馈查询慢了,查看执行计划,走的索引又变成了upper(so_no)。让人头秃。

那还个方向思考,既然走了索引,为什么还会慢!!! 原来走了索引并不一定就会快,这是一个大大的误区。

upper(edibooking0_.so_no) LIKE upper('025%')这个过滤条件走了索引,但是索引的类型是range_scan,这种类型查询返回的数据量会比较大,这就是这次走索引还慢的问题所在,因为走了索引之后返回了150w条数据,而150w条数据被后去的条件过滤,这样导致了查询速度慢的问题。

而引发这个问题,一个是upper(so_no)索引返回数据量大,另外一个就是oracle的执行计划没有选择最优的索引,如果选择tfc_code索引,那么查询也会很快。

三 解决方案

指定数据库选择索引:

由于执行计划是数据库自动生成的,我们无法改变执行计划,但是我们可以通过指定索引的方式,让数据库去执行我们指定的索引,如:

select /*+index(edibooking0_ IDX_EDI_BOOKING_SO_TFC_CT)*/*
FROM edi_booking edibooking0_

但是这种有一个弊端,要对每一个执行的语句都要进行指定索引,修改量比较大。

建立复合索引:

CREATE INDEX IDX_EDI_BOOKING_SO_TFC_CT
ON edi_booking (UPPER("SO_NO"), "TFC_CODE","CONTRACT_NO");

复合索引很容易给人一种鸡肋的感觉,因为他对应的查询条件一定是他最左边的索引字段被查询才能生效,但是其实他是非常有用的,比如我们现在的场景,进行复核索引过滤时就会产生非常大的性能提升,最终通过建立组合索引解决问题

到此这篇关于SQL使用复合索引实现数据库查询的优化的文章就介绍到这了!


Tags in this post...

SQL Server 相关文章推荐
SQL Server 数据库实验课第五周——常用查询条件
Apr 05 SQL Server
【HBU】数据库第四周 单表查询
Apr 05 SQL Server
SQL写法--行行比较
Aug 23 SQL Server
SQL Server表分区删除详情
Oct 16 SQL Server
SQL Server查询某个字段在哪些表中存在
Mar 03 SQL Server
SQL Server数据库基本概念、组成、常用对象与约束
Mar 20 SQL Server
SQL Server数据库查询出现阻塞之性能调优
Apr 10 SQL Server
SQL Server使用PIVOT与unPIVOT实现行列转换
May 25 SQL Server
SQL Server使用CROSS APPLY与OUTER APPLY实现连接查询
May 25 SQL Server
SQL Server一个字符串拆分多行显示或者多行数据合并成一个字符串
May 25 SQL Server
SQL Server中的逻辑函数介绍
May 25 SQL Server
SQL Server中的逻辑函数介绍
May 25 #SQL Server
SQL Server删除表中的重复数据
May 25 #SQL Server
SQL Server中T-SQL标识符介绍与无排序生成序号的方法
May 25 #SQL Server
SQL Server一个字符串拆分多行显示或者多行数据合并成一个字符串
May 25 #SQL Server
SQL Server使用CROSS APPLY与OUTER APPLY实现连接查询
May 25 #SQL Server
SQL Server使用PIVOT与unPIVOT实现行列转换
May 25 #SQL Server
SQL SERVER中的流程控制语句
May 25 #SQL Server
You might like
PHP 字符截取 解决中文的截取问题,不用mb系列
2009/09/29 PHP
php使用gettimeofday函数返回当前时间并存放在关联数组里
2015/03/19 PHP
php使用PDO事务配合表格读取大量数据插入操作实现方法
2017/02/16 PHP
详解PHP字符串替换str_replace()函数四种用法
2017/10/13 PHP
jquery隐藏标签和显示标签的实例
2013/11/11 Javascript
JS使用replace()方法和正则表达式进行字符串的搜索与替换实例
2014/04/10 Javascript
jQuery插件cxSelect多级联动下拉菜单实例解析
2016/06/24 Javascript
jQuery判断是否存在滚动条的简单方法
2016/09/17 Javascript
实例解析angularjs的filter过滤器
2016/12/14 Javascript
JS中实现函数return多个返回值的实例
2017/02/21 Javascript
vue.js异步上传文件前后端实现代码
2017/08/22 Javascript
vue.js使用代理和使用Nginx来解决跨域的问题
2018/02/03 Javascript
vue中的模态对话框组件实现过程
2018/05/01 Javascript
React 组件渲染和更新的实现代码示例
2019/02/21 Javascript
微信小程序左右滚动公告栏效果代码实例
2019/09/16 Javascript
vue实现div单选多选功能
2020/07/16 Javascript
[55:54]FNATIC vs EG 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python编程实现双击更新所有已安装python模块的方法
2017/06/05 Python
python函数中return后的语句一定不会执行吗?
2017/07/06 Python
面向初学者的Python编辑器Mu
2018/10/08 Python
python面向对象入门教程之从代码复用开始(一)
2018/12/11 Python
python实现函数极小值
2019/07/10 Python
Python中的流程控制详解
2021/02/18 Python
CSS3 函数技巧 用css 实现js实现的事情(clac Counters Tooltip)
2017/08/15 HTML / CSS
HTML5中form如何关闭自动完成功能的方法
2018/07/02 HTML / CSS
Java程序员面试90题
2013/10/19 面试题
拓展策划方案
2014/06/03 职场文书
考试作弊被抓检讨书
2014/10/02 职场文书
学习雷锋精神活动总结
2015/02/06 职场文书
客户答谢会致辞
2015/07/30 职场文书
最新的离婚协议书范本!
2019/07/02 职场文书
win10下go mod配置方式
2021/04/25 Golang
Python爬虫之爬取哔哩哔哩热门视频排行榜
2021/04/28 Python
React如何创建组件
2021/06/27 Javascript
Linux安装apache服务器的配置过程
2021/11/27 Servers
Django框架中视图的用法
2022/06/10 Python