前言

在我们进行数据分析的时候,首要的目标是根据业务逻辑,通过编写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. noip模拟赛 小Y的问题

    [问题描述]有个孩子叫小 Y,一天,小 Y 拿到了一个包含 n 个点和 n-1 条边的无向连通图, 图中的点用 1~n 的整数编号.小 Y 突发奇想,想要数出图中有多少个“Y 字形”.一个“Y 字形” ...

  2. 基础算法(java版本)

    Practice Author: Dorae Date: 2018年10月11日13:57:44 转载请注明出处 具体代码请移步git 基础算法 图 Prim Kruskal Dijkstra Flo ...

  3. HDU——2067 小兔的棋盘

    小兔的棋盘 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  4. codevs——1675 大质数 2

    1675 大质数 2  时间限制: 1 s  空间限制: 1000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 小明因为没做作业而被数学老师罚站,之 ...

  5. Ubuntu 16.04安装WPS

    1.下载 http://community.wps.cn/download/ 根据需要对应版本进行下载deb包. 2.安装 sudo dpkg -i wps-office_10.1.0.5672~a2 ...

  6. new出来的对象无法调用@Autowired注入的Spring Bean

    @Autowired注入Spring Bean,则当前类必须也是Spring Bean才能调用它,不能用new xxx()来获得对象,这种方式获得的对象无法调用@Autowired注入的Bean. 1 ...

  7. postgresql备份和恢复

    备份: pg_dump -d m3vg -h localhost -p 5432 -U delta -W -f 1024.dump -F tar 恢复: pg_restore -h localhost ...

  8. 微信企业号开发:corpsecret究竟在哪块呢?

    开发微信企业号,获取ACCESS_TOKEN是必须的,但怎样获取ACCESS_TOKEN呢? 获取access_token=ACCESS_TOKEN" style="text-de ...

  9. android混合动画实现

    在android开发,我们会常常使用到动画,可是简单的一种动画(如旋转.缩放.渐变.位移等)有时候并不能满足我们项目的要求,这时候就须要运用到混合动画.那么在安卓中是怎样实现一个炫酷的混合动画,以下是 ...

  10. C++学习之extern "C"

    我们知道,extern关键字可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.这里起到的是声明作用范围的用处.另外,extern还可以与 ...