让SQL再快一点儿
文章转载自「开发者圆桌」一个关于开发者入门、进阶、踩坑的微信公众号
SQL即结构化查询语言(Structured Query Language),是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系型数据库系统。
从接触编程到现在一直从事和数据库相关的工作,SQL是我使用时间最长的程序语言,没有之一。
关于SQL优化的文章网上很多,很具体,写的很不错,这里不再赘述。这篇文章将会结合平时工作中遇到的问题和经验心得来阐述如何做好SQL优化,其中有错误和不足的地方,还请大家纠正补充。
对于数据库优化有两个层面,一是SQL优化,属于业务层优化;一是数据库设计、表空间规划、缓存等属于管理层面的优化,我们这里只讨论SQL优化这个层面。
接受挑战
不要被运行效率低下或者复杂的SQL吓倒,要勇于接收它的挑战,问题很明确就是要把这个SQL优化快一点,解决方法肯定比遇到的问题多。
越是运行慢,越是复杂的SQL优化的空间就越大。
分析场景
数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。
OLTP 系统强调数据库内存效率,强调内存各种指标的命令率,强调绑定变量,强调并发操作,对于SQL的执行效率有很高的要求;
OLAP 系统则强调数据分析,强调SQL执行时机,强调磁盘I/O,强调分区等。
OLTP要求事务一致性和快速执行,SQL执行时间一般以毫秒或者秒为单位;OLAP对事务一致性要求不高,SQL执行时间以分钟或者小时为单位。因此,不同的业务场景,SQL优化的方法也是不同的。
定位SQL优化点
由于数据库产品、参数配置甚至同一款产品的不同发行版本都会导致同一条SQL出现不同的运行效率。随着业务数据的增长,原本运行良好的SQL也会出现瓶颈。
变化再多也有规律可循,SQL运行效率低根本的问题就是SQL表关联太多、SQL逻辑太复杂、表数据量太大、未使用索引等,这些就是我们要优化的点。
拿到运行效率低的SQL以后,要分析一下该条SQL用到哪些表?哪些索引?表中的数据量是多少?对整个SQL运行的基础环境有一个清晰的认识。
优化SQL最常用的辅助工具就是数据库本身提供的“执行计划”,如何开启、使用执行计划分析和优化SQL,可点击文章最后左下角「阅读原文」查看之前整理的一篇关于《数据库SQL执行计划应用初探》的文章。
进行SQL优化
定位到SQL执行效率低下的原因以后,要想办法优化它,下面是一些通用的处理思路,可以参考一二。
索引;索引是关系型数据库中SQL优化的利器,设计良好的索引以及在SQL中正确应用索引基本上能解决大部分的SQL优化问题。可以通过执行计划分析SQL中索引的应用情况。
变通;3+6与4+5的结果都是9,做事的方式并不是唯一的,可能一种SQL写法效率很低,然而你换一个思路试试其他的写法,效率会有很大的提升,这个需要不断的尝试和摸索。
举个栗子,以Oracle为例查询公司男性与女性员工的薪资总和
select
(select sum(salary) from employee where sex='男') 男性薪资总和,
(select sum(salary) from employee where sex='女') 女性薪资总和
from dual
更好的写法应该是
select
sum(case when sex='男' then salary else 0 end) 男性薪资总和,
sum(case when sex='女' then salary else 0 end) 女性薪资总和
from employee
我刚入门SQL时,就是采用了第一种写法,逻辑最简单明了,但是一个employee表却被扫描了两次(在没有索引的情况下),随着数据量的增加,这条SQL必然出现效率低的问题,第二种写法就会优化很多,效率更高。这是一个简单不能再简单的变通了(当然是现在看来,当时可能想不到)。
分解;把复杂的一条SQL可以拆解为多条简单SQL分步骤执行,可能你会觉得分步骤执行做了很多额外的工作,但是每条简单的SQL执行的会非常快,整体上提升了SQL执行效率。
SQL分解最常用的就是创建中间表,中间表只保存需要的字段和数据行,同时增加必要的索引,可大大提升SQL的执行效率。
环境;SQL优化要在同一个环境中进行,不同的环境中SQL执行路径可能是不同的,优化的方法也是不同的。尽量排除环境因素对SQL优化的影响。
经验;经验很重要,但是避免陷入经验主义。你可能在Oracle中有着非常丰富的SQL优化经验,但是在DB2数据库中可能就不灵了,不要纠结,这很正常。在我从Oracle数据库转向DB2数据库时就出现了很多问题,在Oracle中积累的经验转移到DB2中行不通,只能另辟蹊径。
SQL优化需要经验,但是不能太依赖经验,要不断调整自己的思路。每款数据库产品都有自己的特点,要了解它们,然后去不断应用。好在大部分的经验是通用的,只是略加调整即可,不要太大压力。
把平时优化SQL的技巧和方法总结下来,在真实的SQL优化场景中反复使用和调整,逐渐形成自己的一套优化经验。
总结
上面总结了一些我个人的SQL优化经验,包治百病的良药是不存在的,具体问题还是需要当事人具体分析,优化思路是相通的。
SQL优化这事儿不需要刻意为之,当你写的SQL不满足业务要求时自然就要优化,每次的SQL优化都会不断提升你的优化能力和思考方式。
让SQL再快一点儿的更多相关文章
- 前端通信:ajax设计方案(八)--- 设计请求池,复用请求,让前端通信快、更快、再快一点
直接进入主题,本篇文章有点长,包括从设计阶段,到摸索阶段,再到实现阶段,最后全面覆盖测试阶段(包括数据搜集清洗),还有与主流前端通信框架进行对比PK阶段. 首先介绍一下一些概念: 1. 浏览器的并发能 ...
- [No00001F]阅读速度如何快一点、再快一点?-不知道读啥?试试这些电影剧本!
少侠萌好,还记得包大人给大家推荐过的语感培养大法——“电影剧本阅读法”吗?最近,包大人陆陆续续收到了好几位少侠的实践报告,他们中不少人抱怨:“大人,你明明说过电影剧本篇幅短.用词简单的,可为什么我还是 ...
- 让PETSc跑得再快一些
最近做了一个使用PETSc来求解线性方程组(Ax=b)的项目,把其中遇到的一些坑和解决方法记录下来.本文不介绍PETSc如何入门,而是给出一些能让PETSc运行得更快的编程细节.开始我只是简单地修改P ...
- netty系列之:让TCP连接快一点,再快一点
简介 经典的TCP三次握手大家应该很熟悉了,三次握手按道理说应该是最优的方案了,当然这是对于通用的情况来说的.那么在某些特殊的情况下是不是可以提升TCP建立连接的速度呢? 答案是肯定的,这就是今天我们 ...
- 如何让你的SQL运行得更快
人们在使用SQL时往往会陷入一个误区,即太关注于所得的结果是否正确,而忽略了不同的实现方法之间可能存在的性能差异,这种性能差异在大型的或是复杂的数据库环境中(如联机事务处理OLTP或决策支持系统DSS ...
- 【重磅干货】看了此文,Oracle SQL优化文章不必再看!
目录 SQL优化的本质 SQL优化Road Map 2.1 制定SQL优化目标 2.2 检查执行计划 2.3 检查统计信息 2.4 检查高效访问结构 2.5 检查影响优化器的参数 2.6 SQL语句编 ...
- InnoDB还是MyISAM 再谈MySQL存储引擎的选择
两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用. 我作为使用MySQL的用户角度出发,Innodb和My ...
- 数据库性能优化:SQL索引
SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱. 1.1 什么是索引? SQL索引有两种,聚集索引和非聚集索引 ...
- SQL索引一步到位
以下均非原创,仅供分享.学习!!! SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱. 1.1 什么是索引? S ...
随机推荐
- EhLib DBGridEh组件在Delphi中应用全攻略总结(转)
EhLib DBGridEh组件在Delphi中应用全攻略总结(转) http://blog.sina.com.cn/s/blog_94b1b40001013xn0.html 优化SQL查询:如何写出 ...
- 关于oracle导出时的query用法
QUERY参数后面跟的是where条件,值得注意的是,整个where子句需要使用""括起来,where子句的写法和SELECT中相同: 如果是UNIX平台所有"和'都需 ...
- 你真的懂ajax吗?
前言 总括: 本文讲解了ajax的历史,工作原理以及优缺点,对XMLHttpRequest对象进行了详细的讲解,并使用原生js实现了一个ajax对象以方便日常开始使用. damonare的ajax库: ...
- 开源第三方登录组件OAuthLogin2.0 支持QQ,阿里巴巴,淘宝,京东,蘑菇街,有赞等平台
Nuget地址:https://www.nuget.org/packages/OAuthLogin2.0/ 项目结构说明: AuthorizationProviders文件夹下主要存放内置的授权平台. ...
- 自定义滚动条Js简版
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>自定义滚 ...
- 关于自定义的 XIB cell上的 button如何在控制器里实现点击方法
直接调用cell.button addTarget 的方法点击事件是失效的 这时需要你在xib中设置button的tag值 然后在返回cell的时候添加点击事件 UIButton *button = ...
- python中文编码问题深入分析(一):字符编码基础
背景:笔者作为一名刚接触python语言的新手,在实际的项目中,遇到过一些中文编码问题,初次遇到这些问题的时候,刚开始显得有些手足无措,也不知从何查起.常言道:有问题,找度娘!当我打开www.baid ...
- linux系统盘使用率达到100%的问题查找和解决方法
今天公司云服务器报警系统发来短信,系统磁盘空间不够,登录服务器进行查看,磁盘使用虑达到100%, 感觉比较奇怪,所存的东西并不多,怎么会将磁盘占满,而且数据都是存在数据盘下,通过简单的进行 ...
- PHP静态成员变量
静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员.. ...
- Android jni 编程2(对基本类型一维整型数组的操作)
参考教程和这位博主的对一维数组的处理,主要包括以下三种类型: //传入一维数组,无返回值 public native void arrayEncode(int[] arr); //传一个一维数组和数组 ...