前言

在我们进行数据分析的时候,首要的目标是根据业务逻辑,通过编写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. poj 3164 最小树形图模板!!!

    /* tle十几次,最后发现当i从1开始时,给环赋值时要注意啊! 最小树形图 */ #include<stdio.h> #include<string.h> #include& ...

  2. C++ - new delete 高维数组小结

    借鉴:http://www.cnblogs.com/beyondstorm/archive/2008/08/26/1276278.html http://www.cnblogs.com/platero ...

  3. nyoj_278_排队_201403282135

    排队 时间限制:3000 ms  |  内存限制:65535 KB 难度:1   描述 周末了,软件ACM的队员准备玩玩游戏,娱乐一下,CY想了一个好主意,所有队员站成一个圈,从1开始报数,凡是报出指 ...

  4. Diagnose High-Latency I/O Operations Using SystemTap

    Luca Canali on 28 Jul 2015 Topic: this post is about some simple tools and techniques that can be us ...

  5. 1.5 - 动态路由协议ISIS

    IS-IS 特征: 1:协议操作起来,比OSPF要简单 2:扩展性比OSPF要好,易于扩展 3:对IPv6有很好的支持 4:能够同时支持IP网络,和CLNS网络(OSI网络)(集成的IS-IS) 5: ...

  6. [Mini Programe] Upload Images

    Code for upload iamges: chooseImage: choose the images to upload previewImage: preview the image and ...

  7. Redis源代码分析(三十)--- pubsub公布订阅模式

    今天学习了Redis中比較高大上的名词,"公布订阅模式".公布订阅模式这个词在我最開始接触听说的时候是在JMS(Java Message Service)java消息服务中听说的. ...

  8. HTTP 错误 404.15 - Not Found 请求筛选模块被配置为拒绝包含的查询字符串过长的请求。

    HTTP 错误 404.15 - Not Found 请求筛选模块被配置为拒绝包含的查询字符串过长的请求. 2018-04-20 14:00 by 码农小周, 21 阅读, 2 评论, 收藏, 编辑 ...

  9. git diff比较使用

    git diff 等同于 git diff HEAD jiqing@ubuntu:/home/wwwroot/default/siemens/new_hotel$ git diff HEAD diff ...

  10. TensorFlow alexnet在华为Mate10上运行方法

    我使用的caffe模型:https://github.com/BVLC/caffe/tree/ea455eb29393ebe6de9f14e88bfce9eae74edf6d/models/bvlc_ ...