背景 

  最近SSIS的开发过程中遇到几个问题。其中使用CTE时,遇到一个远程连接对象,结果导致严重的性能问题,为了应急我就修改了代码。

  之前我写了一篇介绍CTE的随笔包含了CTE的用法等:

http://wudataoge.blog.163.com/blog/static/80073886200961652022389/

问题

  在一个数据查询中遇到一个远程连接对象,然后使用了CTE,然后本地查询与远程对象的CTE进行了left join 。下面就是执行计划:

首先我们发现,最后一个操作符显示远程查询占了99%。

注意:

首先,远程查询使用的是CTE的表达式,我对CTE的理解有以下几点:

1.一次性视图(ADHoc View)。即必须后面跟着相应的select、insert、update等,只能用一次。

2.CTE表达式也是在内存中创建了一个表并对其操作。

3.with as 部分仅仅是一个封装定义的对象,并没有真的查询。

3.除非本身具有索引否则CTE中是没有索引和约束的。

4.没有专门的统计信息,这点与表变量很像。有可能会有错误的统计信息。

其次,连接操作符使用的是循环嵌套的操作符。这样就几何翻倍了查询的时间。

这里需要说一下NestedLoops:

本质上讲,“Nested Loops”操作符就是:为每一个记录的外部输入找到内部输入的匹配行。

技术上讲,这意味着外表聚集索引被扫描获取外部输入相关的记录,然后内表聚集索引查找每一个匹配外表索引的记录。

以上两个说法都表明了这种方式导致的性能问题。因为每一次循环都要访问一次链接服务器。当数据很大的时候极大地增加了查询时间。我这边70000+的数据执行了半小时。

解决:

既然了解了问题的情况,那我就着手解决问题。主要是两分解成两个步骤:

1.将远程链接服务器的查询结果插入临时表。

2.本地数据与临时表做left join。

对应的执行计划如下:

可以看到整个性能得到了极大的提高。修改完成后执行时间缩减到20秒以内。效率还是惊人的。

可以对比一下表变量与cte表倒是不同的特点:

  • tempdb中实际存在的表
  • 能索引
  • 有约束
  • 在当前连接中存在,退出后自动删除。
  • 有由引擎生成的数据统计。

通过两个方式的不同点可知几种情况不应当使用CTE:

1.结果集较大时不应使用。

2.查询时间较长的不要使用,比如跨服务器查询。

3.需要大的表连接的,比如行很多的各种join。尤其没有索引。

4.多次查询数据。

5.需要优化相关子查询。

这些时候使用临时表甚至表变量将会带来性能的提升。具体我就不在这里细说了有兴趣可以一起讨论下。

一些网上的错误:

1.materialize 提示 可以强制将WITH AS短语里的数据放入一个全局临时表里。sql server中根本没有这个提示。据说2014以后可能会有?

2.CTE 性能要差,根据实际情况出发,据我所知在绝大多数情况下,CTE的性能要好。尤其是对比游标(迭代)和内置函数的情况下,都会大大提高性能。

3.CTE使用了tempdb,没有仅仅使用了内存。

总结:

  通过解决实际问题,让我了解了CTE的运行机制。可以理解为一种一次性的视图。当然我们这里需要着重说明,CTE本身在性能优化上还是有很大作用的,尤其对于递归查询和内置函数的使用时都极大的较少了IO。

我猜想CTE内部原理应该与游标相似,但是极大的简化了性能,也许是优化器的功劳。最后由于仅仅使用了内存中这样也大大减少了连接瓶颈。

  这部分很多是我的个人观点,希望各位大神帮忙指摘一下。

SQL优化技巧--远程连接对象引起的CTE性能问题的更多相关文章

  1. SQL优化技巧

    我们开发的大部分软件,其基本业务流程都是:采集数据→将数据存储到数据库中→根据业务需求查询相应数据→对数据进行处理→传给前台展示.对整个流程进行分析,可以发现软件大部分的操作时间消耗都花在了数据库相关 ...

  2. 常用的7个SQl优化技巧

    作为程序员经常和数据库打交道的时候还是非常频繁的,掌握住一些Sql的优化技巧还是非常有必要的.下面列出一些常用的SQl优化技巧,感兴趣的朋友可以了解一下. 1.注意通配符中Like的使用 以下写法会造 ...

  3. 数据库的规范和SQL优化技巧总结

    现总结工作与学习中关于数据库的规范设计与优化技巧 1.规范背景与目的 MySQL数据库与 Oracle. SQL Server 等数据库相比,有其内核上的优势与劣势.我们在使用MySQL数据库的时候需 ...

  4. 本地数据库(SQL Server)远程连接服务器端服务器

    本地数据库(SQL Server 2012) 连接外网服务器的数据库,外网的服务器端需要做如下配置: 1. 首先是要打开 数据的配置管理工具 2. 配置相关的客户端协议,开启TCP/IP 3. 数据库 ...

  5. 配置SQL Server 2005 远程连接(转)

    方法如下:  一.为 SQL Server 2005 启用远程连接1. 单击"开始",依次选择"程序"."Microsoft SQL Server 2 ...

  6. sql server2008禁用远程连接

    1.打开SQL Server 配置管理器,双击左边 SQL Server 网络配置,点击TCP/IP协议,在协议一栏中,找到 全部侦听,修改为否,然后点击IP地址,将IP地址为127.0.0.1(IP ...

  7. SQL Server 的远程连接(转载)

    SQL Server默认是不允许远程连接的,如果想要在本地用SSMS连接远程服务器上的SQLServer2012数据库,需要确认以下环节: 1)如果是工作组环境,则需要使用SQL Server身份验证 ...

  8. SQL Server "允许远程连接到此服务器" 配置

    在SQL Server的属性-->连接中我们可以看到这样一个选项:'允许远程连接到此服务器'(英文是remote access),其默认值是1,表示此选项开启. 但是这个参数并非是字面上所显示的 ...

  9. 配置sql server 允许远程连接

    如果要想远程连接数据库那么则需要在一个局域网中或一个路由器中才可以做到 接下来就是具体的操作检查sqlserver数据库是否允许远程连接 具体操作为 (1)打开数据库,用本地帐户登录,右击第一个选项, ...

随机推荐

  1. mysql对表操作的各种语句

    创建表 create table tb_user( id int(类型)primary key(设置为主键) auto_increment (设置id自增长), 每一个字段用逗号隔开, name va ...

  2. CentOS 6.5 搭建 LAMP 环境

    目录 第一步: 安装和配置Apache服务器 第二步: 设置.绑定站点目录文件 第三步: 安装MYSQL数据库 第四步: 安装PHP环境 总结 >>Begin: 第一步: 安装和配置Apa ...

  3. mysql 5.6启用强密码

    mysql的密码策略通过插件的方式进行检查,插件的名称是validate_password,可通过如下方式安装: mysql> INSTALL PLUGIN validate_password ...

  4. 命令行工具解析Crash文件,dSYM文件进行符号化

    备份   文/爱掏蜂窝的熊(简书作者)原文链接:http://www.jianshu.com/p/0b6f5148dab8著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 序 在日常开发 ...

  5. JavaScript基础系列(变量与类型)

    以下内容将JavaScript简称为JS 打开本文时不管你是零基础的初学者还是其他语言的老兵,我都想说程序语言的基础支撑起了整个网络世界,不把这些基础学透之后稍复杂的内容会让你寸步难行. 现在先给编程 ...

  6. HtmlAgilityPack---Html解析框架

    如果你想从一段HTML中提取出指定的标记(如:获取所有的div.获取具有指定属性的元素)如果你想编辑一段HTML,修改里面的部分元素如果你想判断一段HTML中指定元素的关系(子节点.父节点.兄弟节点. ...

  7. canvas画布在主流浏览器中的尺寸限制

    通过测试发现,canvas在不同浏览器下面有不同的最大尺寸限制. 大家都知道,canvas有自身的width,height属性来控制尺寸,用css的width,height,控制显示的大小.可以理解为 ...

  8. 总结CSS3新特性(Animation篇)

    动画(Animation),是CSS3的亮点.//之一 通过animation属性指定@keyframe来完成关键帧动画; @keyframe用法: @keyframes name { 0% { to ...

  9. Listbox与Listbox with key的区别

    标准解释: ListboxVisualization as listbox in which a list of entries is displayed with one short descrip ...

  10. 应用matplotlib绘制地图

    #!/usr/bin/env python # -*- coding: utf-8 -*- from math import sqrt import shapefile from matplotlib ...