对大型数据集的 CUBE 操作非常昂贵,因此您需要检查您是否真的需要内部查询中的所有数据。因为我看到你在内部做 COUNT,然后在外部查询中你有计数的总和。所以换句话说,给我所有组合 A1-A8 (-A7) 的 A7 的行数。然后只获取由 WHERE 子句过滤的选定组合的 SUM。我们可以肯定地通过在某些列本身上限制 CUBE 来优化这一点,但到目前为止我注意到的非常明显的事情如下。
如果您使用下面的查询并且有正确的索引 o Table1 和 Table_reject 那么两个查询都可以利用索引并减少需要连接和进一步处理的数据集。我不是 100% 肯定,但是是的,部分 CUBE 处理是可能的,需要检查一下。
聚集索引 --> A8 上需要 Table1 并且 Table_Reject 需要 NAME 上的聚集索引。
非聚集索引--> A3、A9 需要 Table1,B3、B2 需要 Table_reject
SELECT qry1.
(
SELECT A1, A2,A3,A4,A5,A6,A7,A8
FROM table1
WHERE A8 >= NEXT_DAY ( trunc(to_date('17/09/2013 12:00:00','dd/mm/yyyy hh24:mi:ss')) ,'SUN' )
)qry1
LEFT JOIN
(
select B3,B2,ID
from table_reject
where name = 'smith'
)qry2
ON qry1.A3 = qry2.B3 and qry1.A9=qry2.B2
WHERE qry2.ID IS NULL
编辑1:
我试图找出如果您对所有列执行此操作或仅对结果集中需要它的列执行此操作,CUBE 运算符结果会有什么不同。我发现的是 CUBE 函数的工作方式,您不需要在所有列上执行 CUBE。因为最后你只关心由 CUBE 生成的组合,其中 A1 和 A8 不为空。试试这个链接,看看输出。
在此处输入链接描述
Query 1 和 Query2 只是比较 CUBE 结果集的最内部查询。
Query3 和 Query4 是您正在尝试的相同查询,并且您看到两种情况下的结果都相同。
DECLARE @NEXT_DAY DATE = NEXT_DAY ( trunc(to_date('17/09/2013 12:00:00','dd/mm/yyyy hh24:mi:ss')) ,'SUN' )
SELECT distinct A1 ,sum(total) as sum_total FROM
(
SELECT A1,COUNT(A7) AS total,A8
FROM (
select a.a1,a.a7,a.a8
from table1 a
left join (select * from table_reject where name = 'smith') b
on A.A3 = B.B3 and A.A9 =B.B2
where B.ID is null
) t1
WHERE A8 >= @NEXT_DAY
GROUP BY
CUBE(A1,A8)
)INN
WHERE INN.A1 IS NOT NULL AND
INN.A8 IS NOT NULL
GROUP BY A1
ORDER BY sum_total DESC ;
编辑3
正如我在评论中提到的,这是一个 Round3 更新。我无法更改评论,但我的意思是 Edit3 而不是 Round3。
以及查询中的新变化是WHERE A8 >= @NEXT_DAY
在最里面的左连接选择where A8 >= @NEXT_DAY AND B.ID is null
中添加条件。这极大地改善了选择。
在您的上一条评论中,您提到查询需要 30-35 秒,并且随着您更改 A8 的值,它会不断增加。现在有了执行时间,您没有提到结果集中有多少数据。为什么这很重要? 因为如果我的查询返回 5M 行作为最终结果集,那将花费 90% 的时间将该数据放到 UI 上,或者输出文件,无论您使用什么输出方法。但实际性能应该衡量查询开始提供前几行的时间。因为到那时优化器已经决定了执行计划,而数据库正在执行该计划。但我同意,如果查询返回 100 行并花费 10 秒,那么执行计划可能有问题。
演示我所做的是我创建了虚拟数据。并针对它执行您的查询。我有表 Test_CubeData,其中有 9M 行,列号和数据类型与您为表 1 解释的相同。我有第二个表 Table_Reject ,它有 80K 行,列数和我从查询中得出的数据类型。测试该表的极端情况;name 列只有一个值“smith”,所有 80K 行的 ID 为空。所以可能影响内部左连接结果的列值将是 B2 和 B3。
在这些测试中,我在两个表上都没有任何索引。两者都是堆。并且您会在几秒钟内看到结果,结果集中的数据范围可以接受。随着我的结果数据集增加,完成时间增加。如果我创建解释索引,那么它将为所有这些测试用例提供 Index Seek 操作。但在某些时候,该索引也会耗尽并成为索引扫描。一个肯定的例子是,如果我的 A8 列的过滤器值是该列中存在的最小日期值。在这种情况下,优化器将看到所有 9M 行都需要参与内部选择和 CUBE,并且大量数据将在内存中进行处理。这是预期的。另一方面,让我们看看另一个查询示例。我在 A8 列中有唯一的 32873 个值,这些值几乎平均分布在 9M 行中。所以每个 A8 值有 260 到 300 行。现在如果我执行查询对于任何单个值的最小、最大或查询执行时间之间的任何事物都不应更改。
请注意下面每个图像中突出显示的文本,指示选择了 A8 过滤器的值,仅在选择列表中使用 * 的重要列,在内左连接查询中添加 A8 过滤器,执行计划显示两个表上的 TableScan 操作,以秒为单位的查询执行时间,以及查询返回的总行数。
我希望这将消除您对查询性能的一些疑问,并帮助您设定正确的期望。
**Table Row Counts**
**TableScan_InnerLeftJoin**
**TableScan_FullQuery_248Rows**
**TableScan_FullQuery_5K**
**TableScan_FullQuery_56K**
**TableScan_FullQuery_480k**