当前位置: 首页 > 面试题库 >

递归相关表达式如何加速不同的查询?

公西毅
2023-03-14
问题内容

我发现这篇文章是关于加快不同查询的速度的:

使用递归CTE的超快DISTINCT:

USE     tempdb;
GO
DROP    TABLE dbo.Test;
GO
CREATE  TABLE 
        dbo.Test 
        (
        data            INTEGER NOT NULL,
        );
GO
CREATE  CLUSTERED INDEX c ON dbo.Test (data);
GO
-- Lots of duplicated values
INSERT  dbo.Test WITH (TABLOCK)
        (data)
SELECT  TOP (5000000)
        ROW_NUMBER() OVER (ORDER BY (SELECT 0)) / 117329
FROM    master.sys.columns C1,
        master.sys.columns C2,
        master.sys.columns C3;
GO



SET     STATISTICS TIME ON;

-- 1591ms CPU
SELECT  DISTINCT 
        data
FROM    dbo.Test;

-15ms CPU

WITH    RecursiveCTE
AS      (
        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 < T.data
                ) R
        WHERE   R.rn = 1
        )
SELECT  *
FROM    RecursiveCTE
OPTION  (MAXRECURSION 0);

SET     STATISTICS TIME OFF;
GO
DROP    TABLE dbo.Test;

递归CTE的效率是100倍:-)这种加速对我当前的项目非常有价值,但是我不确定这种方法在哪种情况下是有益的。

老实说:我不明白为什么这会大大加快查询速度,以及为什么数据库本身无法进行此优化。您能解释一下它是如何工作的以及为什么如此有效吗?

编辑:我在sybase上看到类似的效果,因此这种方法似乎仅对sql-server无效。

子问题:递归CTE对其他数据库系统也有用吗?


问题答案:

保罗·怀特(Paul White)在“ 查找不同的值”*
部分的“性能优化整个查询计划”一文中详细解释了该“技巧” 。
*

为什么数据库本身无法进行此优化?

递归CTE是否对其他数据库系统也有用?

优化器不是完美的,它没有实现所有可能的技术。人们要求微软实施它。请参阅此连接项“实施索引跳过扫描”。由于无法修复,因此已关闭,但这并不意味着将来不会解决。其他DBMS可能已经实现了它(Connect项目说Oracle实现了此优化)。如果在DBMS引擎中实现了这种优化,则不需要此“技巧”,优化器将根据可用统计信息选择计算结果的最佳方法。

我不明白为什么这会大大加快查询速度。

我不确定这种方法在哪种情况下是有益的

简单DISTINCT查询将扫描整个索引。“扫描”表示它从磁盘读取索引的每一页,并汇总内存(或tempdb)中的值以获取不同值的列表。

如果您知道表有很多行,但是只有几个不同的不同值,那么读取所有这些重复值将浪费时间。递归CTE强制服务器为第一个不同的值寻找索引,然后为第二个值寻找索引,依此类推。“搜索”表示服务器在索引中使用二进制搜索来找到该值。通常,一次查找仅需要从磁盘读取几页。“索引”是一棵平衡的树。

如果表只有几个不同的值,则查找几次的速度要比读取索引的所有页的速度快。另一方面,如果有很多不同的值,那么顺序地读取所有页面比寻找每个连续的值要快。这应该使您知道在什么情况下此方法是有益的。

显然,如果表很小,则扫描它会更快。只有当表格变得“足够大”时,您才开始看到性能上的差异。

dba.se上有一个相关的问题:是否有可能针对不同/分组依据获得基于搜索的并行计划?



 类似资料:
  • 我希望有一个regex来匹配以开头的所有行,后面跟着以开头的任意数量的行。理想情况下,我希望将带有的每一行放在一个组中。 以下是我希望得到的结果: (为了缩短起见,我用了[...]。) 它实际上给了我这个: 我希望我已经说得够清楚了,你能帮我解决这个问题。请不要犹豫,询问更多的细节。

  • 问题内容: 这与正则表达式匹配外括号非常相关,但是,我特别想知道该 正则表达式的递归模式 如何或是否可行? 我尚未找到使用此策略的python示例,因此认为这应该是一个有用的问题! 我已经看到 了一些 索赔 是递归的模式可以用来匹配平衡括号,但使用Python的没有例子正则表达式包(注:重 不 支持递归模式,你需要使用正则表达式)。 一种说法是语法位于: 是开始构造的东西,是可能在构造中间发生的东

  • 本文向大家介绍正则表达式速查表,包括了正则表达式速查表的使用技巧和注意事项,需要的朋友参考一下 字符 字符类 预定义字符类 POSIX 字符类(仅 US-ASCII) java.lang.Character 类(简单的 java 字符类型) Unicode 块和类别的类 边界匹配器 Greedy 数量词 Reluctant 数量词 Possessive 数量词 Logical 运算符 Back 引

  • 我只是想递归地定义一个Java8lambda表达式。 我发现使其工作的一种方法是使用一个数组来引用lambda,有效地欺骗了java编译器: 定义递归lambda表达式还有其他技巧吗?

  • 问题内容: 该字符串可以类似于以下之一: 我想匹配不限数量的“ a(x,y)”。如何使用Regex做到这一点?这是我所拥有的: 它仅匹配“ a(x,y)”的两个递归。 问题答案: Java的标准正则表达式库不支持递归,因此您无法将此类通用嵌套结构与之匹配。 但是在确实支持递归的版本(Perl,PCRE,.NET等)中,您可以使用以下表达式:

  • 字符串可以类似于以下内容之一: 我想匹配无限数量的“a(x,y)”。我如何使用正则表达式来实现这一点?以下是我所拥有的: 它只匹配"a(x, y)"的两个递归。