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. Apache本地环境下出现循环重定向

    最近发现一个很奇怪的问题,用了很久的apache+php访问项目,昨天突然不行了,出现了这个 然后我一点点测试,我用的是TP框架,Indexaciton的index中调用框架里的一个redirect函 ...

  2. 巧用hidden传递参数

  3. "库未注册"(Library not registered)异常.

    启发链接:http://social.msdn.microsoft.com/Forums/vstudio/en-US/f25b80bc-ecd4-4c37-8be3-9106a765b072/libr ...

  4. CI 笔记3 (easyui 和 js 排错)

    开始使用easyui作为后台框架,做layout布局,浏览器白屏,报告异常,除错过程步骤如下: 浏览器加载easyui后,布局的north,south,west,east,center,没有起作用,在 ...

  5. jQuery 停止动画

    jQuery stop() 方法用于在动画或效果完成前对它们进行停止. 停止滑动 点击这里,向上/向下滑动面板 实例 jQuery stop() 滑动演示 jQuery stop() 方法. jQue ...

  6. 求fibonacci数列 java

    java 和 c 差不多.但是java可以根据需求定义数组. 我还不会java的函数调用,所以用数组的方法. import java.util.Scanner; public class fibon{ ...

  7. 根据CreateDirectory递归创建多级目录

    分为MFC下的和非MFC下的两种,MFC路径是CString类型的,非MFC的路径是wstring类型的. 下面是MFC下的创建目录: void __fastcall RecursiveDirecto ...

  8. Qt Quick 与 QML语言(初学笔记1)

    Qt Quick Qt Quick是一些新的UI技术的集合,用来帮助开发者创建一种现在越来越多用于手机.多媒体播放器.机顶盒以及其他便携式设备上的直观的.现代的.流畅的用户界面.简单来说,Qt Qui ...

  9. Dedecms自定义sql 出现错误Safe Alert: Request Error step 2!

    Dedecms自定义执行sql: SELECT body FROM dede_addonarticle WHERE aid = (select max(aid) fromdede_addonartic ...

  10. 阿里云 centos vim 显示中文 乱码

    开始以为是vim 设置编码的问题 :网上搜  改 .vimrc    无效!!! 后转战  是不是系统里面没有中文字体 1.先从你本机 C:\Windows\Fonts 拷贝或者网络上下载你想要安装的 ...