前言

在我们进行数据分析的时候,首要的目标是根据业务逻辑,通过编写SQL代码得到我们想要的结果,这是毋庸置疑的。一般情况下,由于我们分析的数据量比较少,体会不出SQL语句各种写法的性能优劣,对SQL代码的优化往往没那么重要。但是随着数据库中数据的增加,尤其是当一个系统需要对海量的数据进行持续性的分析时,SQL的运行效率就成为系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍甚至更多,可见对于数据分析,不是简单地能实现其功能就可,而是要写出高质量的SQL语句,提高系统的可用性和效率。接下来,将介绍几种常用的SQL优化技巧。

WHERE下多个过滤条件的排列顺序

我们在使用WHERE关键字进行条件筛选时,经常会包含多个筛选条件,使用AND进行连接。数据库在对WHERE关键字进行解析时,采用自下而上的顺序进行,即从最后一个过滤条件向前解析。根据这个原理,那些可以过滤掉最大数量记录的条件应该写在WHERE子句的末尾,以减少数据库需要遍历的数据量。例如,我们要从全网3天的KPI数据中筛选出一个站一天的数据。显然,先筛选基站能尽快滤掉更多的数据。因此,我们应把基站筛选放在后面,写成:

重复记录的处理

在我们进行关联操作时,关联条件字段的异常重复数据是影响运行效率和数据质量的一个重要因素。比如我们要根据enb_id字段关联的两张表,这两张表中各有一千条数据的enb_id值为1(这是很常见的错误)。关联后,重复字段的条目数就变为1000*1000。如果重复字段再多,数据量的指数级增长将极大影响运行效率。因此我们需要对数据进行去重处理。以下介绍一种最高效的删除重复记录的方法:

当然,要在熟悉业务逻辑的情况下进行去重,以免误删正常的重复数据。

WHERE、HAVING和ON的比较

WHERE和HAVING关键字都可以对查询结果进行筛选,两者的区别是WHERE的作用时间是在计算之前就完成的,而having是在计算后才起作用的。HAVING只会在检索出所有记录之后才对结果集进行过滤。 这个处理需要排序,总计等操作。显然WHERE能在计算之前滤掉更多数据,效率更高。因此在不涉及计算的筛选中,应尽量使用WHERE。只有对计算之后的字段进行筛选时才考虑使用HAVING。

ON关键字实际上也是对数据进行筛选,只不过是在多表关联时使用。需要注意的是,在我们常用的操作中,表关联是最耗时的操作之一。尤其是两张大表的关联。因此我们应尽量在关联之前对数据进行汇总和筛选,以减少关联的数据量,提高运行效率。例如以下两段代码:

SQL-1:

SQL-2:

第一条SQL的逻辑是先将两表进行关联,再从关联结果中筛选出符合条件的数据。而第二条SQL的逻辑是先从一张表中筛选出需要的数据,再进行关联得到结果。显然第二条SQL需要进行关联的数据量更少,效率更高,尤其是WHERE条件可以滤掉大量数据的情况下。

灵活使用EXISTS关键字

在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行连接.在这种情况下,通常我们会考虑使用IN关键字,如:

在这种情况下,使用EXISTS或NOT EXISTS通常是查询效率更高的方法。在子查询中,NOT IN子句将执行一个内部的排序和合并。无论在哪种情况下,NOT IN都是最低效的,因为它对子查询中的表执行了一个全表遍历。为了避免使用NOT IN ,我们可以把它改写成外连接或NOT EXISTS。例如,上面的代码我们可以改写为:

同时,巧妙地使用EXIST还可以更高效地在查询一对多表信息时实现DISTINCT效果。例如,我们要从工参中查询KPI中出现的小区都属于哪些地市。如果使用DISTINCT,实现方法如下:

但DISTINCT是一种很低效的查询方式,应尽量避免使用。我们可以充分利用工参中enb_id唯一的特点使用EXIST更高效地实现同样效果。代码如下:

UNION ALL和UNION

UNION和UNION ALL都有合并数据的效果,但也有细微的区别。UNION ALL只是简单的合并,将重复输出两个结果集合中相同记录,而UNION会去除重复记录。实际上,UNION就是先将两个集合以UNION ALL的方式合并,然后在输出最终结果前进行排序去重。因此UNION效率更低。当我们不需要对结果去重的时候,应尽量使用UNION ALL。

表关联的优化

前面我们分析过,表关联是最耗时间的常用操作之一。因此,表关联优化的一个重要原则就是在关联之前尽量减少两张表格的数据量。看以下两段SQL:

SQL-1:

SQL-2:

思考表连接的的SQL执行顺序,前者两张表JOIN后马上筛选部分结果再与另一张表JOIN,后者先将三张表JOIN后再筛选。所以很明显前者效率比后者高。还有另外一种写法:

第三条和第一条SQL一样效率不错。从逻辑上看,似乎SQL会先将表JOIN后再筛选,但实际结果是先筛选再JOIN。因为SQL SERVER会内部分析,产生一个最优的执行计划,自动处理。而如果按照第二种写法使用JOIN ON的话,就好像是使用强制命令,告诉数据库,就是要按你的方式处理结果,数据库只好服从。

但是有一点需要注意,上面的三种写法使用的都是内关联,三种方法的结果是一样的,只是效率不同。如果使用外关联,结果就有区别了。比如使用LEFT JOIN,第一种写法中,将单表的过滤条件写在ON后面,左表中不符合条件的数据也会被保留,无法起到过滤的作用。而第二种写法先关联再筛选,会滤掉不符合条件的数据。这点需要特别注意,以免发生逻辑上的错误。

后记

最后需要说明一点,如今数据库的类型越来越多,数据库的优化器也越来越智能。很多情况下,数据库的优化器会根据数据情况自动对SQL进行优化。比如,Impala数据库中可使用COMPUTE STATS语句收集表的统计信息,这样在对表进行操作的时候,数据库的优化器就可以自动进行SQL优化。再比如,针对表关联中多表排列顺序的问题,在基于规则的时代,查询效率是和表的连接顺序相关的,小表在左、大表在右的执行效率会高一些。但是现在基本上是基于代价的时代,所以大小表的顺序和效率无关,数据库优化器会自动去进行效率优化。但是,理解数据库内部的代码编译逻辑是数据工程师的基本素质,即使很多时候优化器会帮助我们进行代码优化,使我们减少很多思考,但是良好编程习惯的养成无论在任何时候都能使我们在工作中更加得心应手。

sql server 数据分析优化实战(一)——SQL语句优化的更多相关文章

  1. SQL Server Cpu 100% 的常见原因及优化

    SQL Server Cpu 100% 的情况并不太常见,一般引起 SQL Server 产生性能问题的,都是 阻塞.连接数.IO 磁盘等.所以,一般SQL Server 的使用率都是比较低的.但是, ...

  2. SQL SERVER 占用资源高的SQL语句

    --SQL SERVER 占用资源高的SQL语句: --查询占用cpu高的前 50 个 SQL 语句 SELECT total_cpu_time,[total_physical_Reads], tot ...

  3. sql server 2008 数据库管理系统使用SQL语句创建登录用户步骤详解

    介绍了sql server 2008 数据库管理系统使用SQL语句创建登录用户步骤详解 --服务器角色: --固定服务器角色具有一组固定的权限,并且适用于整个服务器范围. 它们专门用于管理 SQL S ...

  4. 从零开始学习SQL SERVER(2)--- 基本操作及语句

    声明:仅为本人随笔及经验之谈,有错误敬请指出. # 后的文字为注释 Microsoft SQL Server Management Studio 中的SQL命令 添加数据库 1 CREATE DATA ...

  5. 一名小小的SQL Server DBA想谈一下SQL Server的能力

    一名小小的SQL Server DBA想谈一下SQL Server的能力 百度上暂时还没有搜索到相关的个人写的比较有价值的文章,至少在中文网络的世界里面没有 但是在微软的网站有这样一篇文章:<比 ...

  6. c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程

    c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...

  7. 基于iSCSI的SQL Server 2012群集测试(二)--SQL群集安装后初始化配置测试

    4.群集安装后初始化配置测试 4.1 禁用full-text 服务和Browser服务 Full-text服务:公司目前暂不使用,需在两个节点上分别禁用 Browser服务:为保证安全,建议将Brow ...

  8. SQL Server审计功能入门:SQL Server审核 (SQL Server Audit)

    原文:SQL Server审计功能入门:SQL Server审核 (SQL Server Audit) 介绍 Audit是SQL Server 2008之后才有的功能,它能告诉你"谁什么时候 ...

  9. 【转】SQL Server 2008 事件探查器(SQL SERVER Profiler)

    跟踪数据库sql语句的执行情况.例:一个系统,用到了sql server 数据库,这个系统共有500张表,当用户在前台页面做某一个操作时,比如插入,登录等等,我们想知道此刻是在对哪一张表操作,打开事件 ...

  10. SQL Server In-Memory OLTP Internals for SQL Server 2016

    SQL Server In-Memory OLTP Internals for SQL Server 2016 这份白皮书是在上一份<SQL Server In-Memory OLTP Inte ...

随机推荐

  1. C# 反射基础

    反射的定义:审查元数据并收集关于它的类型信息的能力.元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等. 公共语言运 ...

  2. HTTP自学心得

    HTTP是一个 客户端和 服务器端请求和应答的标准(TCP).HTTP是客户端浏览器或其他程序与 Web服务器之间的应用层通信协议. HTTP一般指超文本传输协议,它是互联网应用最广泛的协议,是用于从 ...

  3. bridge 上网

    手头有一台机器上有一个虚拟机 虚拟机为桥接 本机为静态IP上网 想让虚拟机上网的方式是 本机不设ip 网卡设置DHCP. 虚拟机设置静态ip

  4. 条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用

    先看第一种情况:返回一个局部对象的引用.它的问题在于,局部对象 ----- 顾名思义 ---- 仅仅是局部的.也就是说,局部对象是在被定义时创建,在离开生命空间时被销毁的.所谓生命空间,是指它们所在的 ...

  5. CN Internet

    来自为知笔记(Wiz)

  6. Windows下擴展ubuntu虛擬機的分區大小

    在虛擬分區上安裝ubuntu,8G的分区不够用,不願意重装,增加VM分区吧!先备份虛擬硬盤文件 VMWARE自带的工具:找到vmware安装目录下vmware-vdiskmanager.exe,双击無 ...

  7. jvm 堆内存 栈内存 大小设置

                        4种方式配置不同作用域的jvm的堆栈内存. 1.Eclise 中设置jvm内存: 改动eclipse的配置文件,对全部project都起作用 改动eclipse ...

  8. Codeforces Round #263 (Div. 1)-A,B,C

    A: 这道题目还是非常easy的,做过非常多遍了.相似于分割木板的问题. 把全部的数放在一个优先队列里,弹出两个最大的,然后合并,把结果放进去.依次进行. #include <iostream& ...

  9. POJ2352 Stars 树状数组

    emm,ssy说可以直接CDQ分治...%%%但是注意到y是有序的,所以可以直接求一下前缀和就行了. 题干: Astronomers often examine star maps where sta ...

  10. JSP-Runoob:JSP 表达式语言

    ylbtech-JSP-Runoob:JSP 表达式语言 1.返回顶部 1. JSP 表达式语言 JSP表达式语言(EL)使得访问存储在JavaBean中的数据变得非常简单.JSP EL既可以用来创建 ...