CTE全名是Common Table Expression,语法基础请参考MSDN文档:https://msdn.microsoft.com/zh-cn/library/ms175972.aspx

CTE Recursion诞生之时,着实让人惊艳了一把。被很多吃瓜群众以讹传讹之后,“慢”似乎成了CTE Recursion最大的原罪。

很多时候,用到CTE Recursion的场景,无非是千八百条的数据量,最大也不过万八千条,所以“慢”算不上个问题。直到前几天,一个群友问:500W的数据做CTE递归时,怎么做性能优化……

结论:

  1. 合理的索引会极大的提升CTE Recursion的性能;
  2. 根据实验结果猜测:Sql Server2016对CTE Recursion做了优化,缺失合理索引的前提下,性能有极大的提升(受测试样本影响,结果可能不准确。无论如何,索引可以帮到你)。

Talk is cheap,Show me the code!所以,原因如下图(样本数据:1W零1条^^):

拒绝耍流氓,测试代码如下:

 IF OBJECT_ID('dbo.TestCte', 'U') IS NOT NULL
DROP TABLE dbo.TestCte;
GO
CREATE TABLE dbo.TestCte
(
Id VARCHAR(10) NOT NULL ,
ParentId VARCHAR(10) NULL
);
WITH cte_001
AS ( SELECT 1 AS a UNION ALL
SELECT 2 AS a UNION ALL
SELECT 3 AS a UNION ALL
SELECT 4 AS a UNION ALL
SELECT 5 AS a UNION ALL
SELECT 6 AS a UNION ALL
SELECT 7 AS a UNION ALL
SELECT 8 AS a UNION ALL
SELECT 9 AS a UNION ALL
SELECT 10 AS a )
INSERT dbo.TestCte
( Id, ParentId )
SELECT RIGHT( '' + CAST ( T01.Id AS VARCHAR(10) ), 10 ) AS Id ,
RIGHT( '' + CAST ( CEILING( T01.Id / 10 ) AS VARCHAR(10) ), 10 ) AS ParentId
FROM (
SELECT ROW_NUMBER() OVER ( ORDER BY cte_001.a ) AS Id
FROM cte_001
CROSS JOIN cte_001 AS A
CROSS JOIN cte_001 AS B
CROSS JOIN cte_001 AS C
CROSS JOIN cte_001 AS D
CROSS JOIN cte_001 AS E
CROSS JOIN (SELECT TOP 5 * FROM cte_001) AS F ) AS T01;
GO INSERT DBO.TestCte ( Id, ParentId )
VALUES ( '', NULL );
GO
 --无索引版本
SET STATISTICS TIME ON;
SET STATISTICS IO ON; IF OBJECT_ID('dbo.T', 'U') IS NOT NULL
DROP TABLE dbo.T;
GO
CREATE TABLE dbo.T
(
RN UNIQUEIDENTIFIER PRIMARY KEY,
Id VARCHAR(10) ,
ParentId VARCHAR(10) ,
Memo1 NVARCHAR(128) DEFAULT ( N'我是占位置的!我是占位置的!我是占位置的!我是占位置的!我是占位置的!' ) ,
Memo2 NVARCHAR(128) DEFAULT ( N'我是很骄傲的!我是很骄傲的!我是很骄傲的!我是很骄傲的!我是很骄傲的!' )
);
INSERT dbo.T
( RN ,
Id ,
ParentId
)
SELECT N.RN ,
N.Id ,
N.ParentId
FROM ( SELECT NEWID() AS RN ,
Id ,
ParentId
FROM dbo.TestCte
WHERE Id < 10001--测试数据量,改这里
) AS N
ORDER BY RN ASC;
GO
WITH cte_001
AS ( SELECT Id ,
ParentId
FROM dbo.T
WHERE ParentId IS NULL
UNION ALL
SELECT T01.Id ,
T01.ParentId
FROM T AS T01
INNER JOIN cte_001 AS T02 ON T02.Id = T01.ParentId
)
SELECT COUNT(*)
FROM cte_001;
 --有索引版本
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
IF OBJECT_ID('dbo.T', 'U') IS NOT NULL
DROP TABLE dbo.T;
GO
CREATE TABLE dbo.T
(
RN UNIQUEIDENTIFIER PRIMARY KEY,
Id VARCHAR(10) ,
ParentId VARCHAR(10) ,
Memo1 NVARCHAR(128) DEFAULT ( N'我是占位置的!我是占位置的!我是占位置的!我是占位置的!我是占位置的!' ) ,
Memo2 NVARCHAR(128) DEFAULT ( N'我是很骄傲的!我是很骄傲的!我是很骄傲的!我是很骄傲的!我是很骄傲的!' )
);
INSERT dbo.T ( RN , Id , ParentId )
SELECT N.RN , N.Id , N.ParentId
FROM ( SELECT NEWID() AS RN , Id , ParentId
FROM dbo.TestCte
WHERE Id < 10001--测试数据量,改这里
) AS N
ORDER BY RN ASC;
GO --创建索引
CREATE NONCLUSTERED INDEX IDX_DBO_T_PARENTID_ID
ON [dbo].[T] ([ParentId], Id)
GO WITH cte_001
AS ( SELECT Id , ParentId
FROM dbo.T
WHERE ParentId IS NULL
UNION ALL
SELECT T01.Id , T01.ParentId
FROM T AS T01
INNER JOIN cte_001 AS T02 ON T02.Id = T01.ParentId
)
SELECT COUNT(*)
FROM cte_001;

CTE Recursion Performance的更多相关文章

  1. TSql CTE 递归原理探究

    CTE是如何进行递归的?产生递归的条件有三个,分别是 初始值 自身调用自身 结束递归的条件 1,示例代码 ;with cte as ( as jd union all as jd from cte ) ...

  2. SQL笔记 - CTE递归实例:显示部门全称

    昨天在整理JS的Function时,示例是一个递归函数.说起递归,想起前段时间在搞CTE,那个纠结呀,看似容易,可我总抓不住门道,什么递归条件,什么结束条件,一头雾水...今天一大早就爬起来,果然不负 ...

  3. Chapter 6 — Improving ASP.NET Performance

    https://msdn.microsoft.com/en-us/library/ff647787.aspx Retired Content This content is outdated and ...

  4. SQL Server CTE 递归查询全解

    在TSQL脚本中,也能实现递归查询,SQL Server提供CTE(Common Table Expression),只需要编写少量的代码,就能实现递归查询,本文详细介绍CTE递归调用的特性和使用示例 ...

  5. SQL Server CTE 递归查询全解 -- 转 学习

    在TSQL脚本中,也能实现递归查询,SQL Server提供CTE(Common Table Expression),只需要编写少量的代码,就能实现递归查询,本文详细介绍CTE递归调用的特性和使用示例 ...

  6. SQL Server CTE 递归查询全解(转载)

    在TSQL脚本中,也能实现递归查询,SQL Server提供CTE(Common Table Expression),只需要编写少量的代码,就能实现递归查询,本文详细介绍CTE递归调用的特性和使用示例 ...

  7. CTE 递归查询全解

    TSQL脚本能实现递归查询,用户使用共用表表达式 CTE(Common Table Expression),只需要编写少量的代码,就能实现递归查询.本文详细介绍CTE递归调用的特性和使用示例,递归查询 ...

  8. 利用临时表实现CTE递归查询

    一.CTE递归查询简介 --CTE递归查询终止条件在TSQL脚本中,也能实现递归查询,SQL Server提供CTE(Common Table Expression),只需要编写少量的代码,就能实现递 ...

  9. Performance Monitor4:监控SQL Server的IO性能

    SQL Server的IO性能受到物理Disk的IO延迟和SQL Server内部执行的IO操作的影响.在监控Disk性能时,最主要的度量值(metric)是IO延迟,IO延迟是指从Applicati ...

随机推荐

  1. google的西联汇款可以使用工行代收

  2. php验证是否为手机端还是PC

    <?php $forasp = strtolower($_SERVER['HTTP_USER_AGENT']); if(strpos($forasp,'mobile')==true) { ech ...

  3. CI 笔记(easyui js命令)

    1. 两种方式加载easyui,一是用class自动渲染,一种是js.建议js. 2. 参考李炎恢的easyui的视频教程.最好的一个视频,对于easyui.

  4. Swift - 使用CoreLocation实现定位(经纬度、海拔、速度、距离等)

    CoreLocation是iOS中一个提供设备定位的框架.通过这个框架可以实现定位处理,从而获取位置数据,比如经度.纬度.海拔信息等.   1,定位精度的设置 定位服务管理类CLLocationMan ...

  5. 绘图quartz之渐变

    实现线性渐变   径向渐变   自己新建的view中有一个drawRect:(cgrect)rect方法 在这个方法里 可以通过画图 将内容显示在画板上(即最下边的view)   渐变的方式分两种   ...

  6. Chrome调试(转)

    原文地址:http://blog.csdn.net/chenmoquan/article/details/44943245#comments 觉得写的很适合web开发的新手 Chrome 的开发者工具 ...

  7. vijos P1055奶牛浴场&& Winter Camp2002

    这道题是我在寒假的模拟赛里碰到的,现在想起来仍觉得余味无穷.题目大意大致如下:给你一个矩形并在其中划出一个最大的子矩形,当然,在这个矩形里有些地方是取不到的,也就是说我们划的这个子矩形不能包含这些点( ...

  8. WPF WebBrowser 不可见问题的解析[转]

    问题概述: 1.在Xaml中加入WebBrowser(不论是WPF中的控件,还是Winform中的控件) 2.设置Window Background="Transparent" A ...

  9. Oracle通过主键id删除记录很慢

    问题描述: Oracle通过主键id删除2000条记录很慢,需要花费十二分钟. 解决过程: 1.首先查看SQL的执行计划,执行计划正常,cost只有4,用到了主键索引. 2.查看等待事件, selec ...

  10. frame,bounds,center-三者的含义

    frame与bounds的区别比较 frame,bounds,center-三者的含义 偶然觉的,这三个属性有时候定位的时候,需要用.于是就来搞清楚,到底frame,bounds,center 这三个 ...