sql – 递归相关表达式如何加快不同的查询?
|
我发现 this post关于加快不同的查询: 使用递归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对其他数据库系统有用吗? 解决方法保罗·怀特在他的帖子 Performance Tuning the Whole Query Plan中非常详细地解释了这个“诡计”,在“寻找不同的价值”部分.
优化器并不完美,并没有实现所有可能的技术.人们要求微软实施.请参阅此连接项目Implement Index Skip Scan.它将被关闭,因为不会修复,但这并不意味着它将来不会被解决.其他DBMS可能已经实现了它(连接项表示Oracle实现了这个优化).如果在DBMS引擎中实现了这种优化,则不需要这种“技巧”,优化器将根据可用的统计信息选择最优的计算结果的方法.
简单的DISTINCT查询扫描整个索引. “扫描”表示它从磁盘读取索引的每个页面,并聚合内存中的值(或tempdb)以获取不同值的列表. 如果你知道表有很多行,但是只有很少的不同的值,那么阅读所有这些重复值就是浪费时间.递归CTE强制服务器寻找第一个不同值的索引,然后寻找第二个值的索引等等. “Seek”表示服务器在索引中使用二进制搜索来查找该值.通常一个搜索需要从磁盘读取几页. “索引”是一棵平衡的树. 如果表只有几个不同的值,则比查阅索引的所有页面要更加快速寻找几次.另一方面,如果有很多不同的值,那么按顺序读取所有页面比搜索每个连续的值更快.这应该给你一个想法在什么情况下这种方法是有益的. 显然,如果桌子很小,扫描速度会更快.只有当桌子变得“足够大”时,才能看到性能上的差异. dba.se有一个相关的问题:Is it possible to get seek based parallel plan for distinct/group by? (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
