我发现这篇文章是关于加快不同查询的: ! Z+ i. r% N! L' d0 L- W7 B0 \使用递归CTE的超快DISTINCT:( z+ e, D$ k# f" Z
USE tempdb;GODROP TABLE dbo.Test;GOCREATE TABLE dbo.Test data INTEGER NOT NULL, );GOCREATE CLUSTERED INDEX c ON dbo.Test (data);GO-- Lots of duplicated valuesINSERT dbo.Test WITH (TABLOCK) (data)SELECT TOP ROW_NUMBER() OVER (ORDER BY (SELECT FROM master.sys.columns C master.sys.columns C2, master.sys.columns C3;GOSET STATISTICS TIME ON;-- 1591ms CPUSELECT DISTINCT dataFROM dbo.Test;-15ms CPU) s, u* K5 w6 {+ i- U+ E" T( d
WITH RecursiveCTEAS SELECT data = MIN(T.data) FROM dbo.Test T UNION ALL SELECT R.data FROM -- A cunning way to use TOP in the recursive part of a CTE Smile SELECT T.data, rn = ROW_NUMBER() OVER (ORDER BY T.data) FROM dbo.Test T JOIN RecursiveCTE R ON R.data 递归CTE效率是100倍:-)这种加速对我目前的项目很有价值,但我不确定这种方法在什么情况下是有益的。* ?7 U1 `0 y8 Y0 U% B$ ?% C# b% z# Q, ^
说实话,我不明白为什么查询速度会大大加快,为什么数据库本身不能优化。你能解释它是如何工作的,为什么它如此有效吗?" X* @+ ]4 e, f
编辑:我在sybase看到类似的效果,所以这种方法似乎只对sql-server无效。% r$ {+ _3 p9 ?- F" N5 Z3 E
子问题:递归CTE对其它数据库系统也有用吗? ' W! F. t6 F$ Z' ^% t f9 q8 c& ?0 R5 A 解决方案: 7 ?3 z; g1 v8 L% z 保罗·怀特(Paul White)在“ 找到不同的值*/ S. q. Y& W9 U6 s2 I
性能优化整个查询计划一文详细说明了技巧 。* ; g5 \1 B/ Z9 F, o, c h5 P为什么数据库本身不能优化这个? $ r7 D6 B& V4 k; O; t递归CTE对其他数据库系统也有用吗? 6 [2 E# e& l+ P5 \优化器并不完美,它还没有实现所有可能的技术。人们要求微软实施它。请参考此连接项实施索引跳过扫描。它已经关闭,因为它无法修复,但这并不意味着它将来不会解决。DBMS它可能已经实现了(Connect项目说Oracle实现这种优化)。DBMS如果这种优化在发动机中实现,则不需要这种技能。优化器将根据可用的统计信息选择计算结果的最佳方法。$ l- o& v9 m/ i- X
我不明白为什么查询速度会大大加快。 / I7 ?! g/ x8 t9 N我不确定这种方法在什么情况下是有益的 + o" Y0 _% W( Z8 f7 N8 ]简单DISTINCT查询将扫描整个索引。扫描意味着它从磁盘上读取索引的每一页,并总结内存(或tempdb)中取不同值的列表。* r2 q& N% H% T& [( o: Z
如果你知道表中有很多行,但只有几个不同的值,读取所有这些重复值将浪费时间。CTE强制服务器为第一个不同的值找到索引,然后为第二个值找到索引,等等。搜索意味着服务器使用二进制搜索来找到索引中的值。通常,搜索只需要从磁盘上读取几页。索引是一棵平衡的树。) v& Y/ ^4 u$ T* R3 O$ J0 t
如果表只有几个不同的值,那么搜索几次的速度比读取索引的所有页面都快。另一方面,如果有许多不同的值,那么顺序读取所有页面比找到每个连续值要快。这应该让你知道这种方法在什么情况下是有益的。2 Y1 T" l9 N4 R9 _ L* \
显然,如果手表很小,扫描会更快。只有当表格变得足够大时,你才会开始看到性能差异。 3 I* U; d1 Z5 w- @# mdba.se有一个相关的问题:基于搜索的并行计划是否有可能获得不同/分组的平行计划?