多个分区子查询的性能
Performance for multiple partitioned subqueries
我有一个包含一个主 table 和多个 history/log table 的数据库,用于存储主 table 的一些行的属性随时间的演变。这些属性并不存储在主table本身,而是必须从相关的history/logtable中查询。所有这些 table 都很大(以千兆字节为单位)。
我想转储整个主要 table 并加入所有 history/log table 的最后一个条目。
目前我通过子查询来实现,如下所示:
WITH
foo AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY date DESC) AS rownumber,
...
FROM table1),
bar AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY date DESC) AS rownumber,
...
FROM table2)
SELECT
...
FROM maintable mt
JOIN foo foo ON foo.itemid = mt.itemid AND foo.rownumber = 1
JOIN bar bar ON foo.itemid = mt.itemid AND bar.rownumber = 1
WHERE ...
问题是这很慢。这个问题有更快的解决方案吗?
我只能对该数据库执行只读查询:我不能对其进行任何更改。
在实际的Oracle版本中,通常使用laterals/CROSS APPLY会更好,因为CBO(oracle cost-based优化器)可以转换它们(DCL - lateral view decorrelation
转换)并使用优化连接方法取决于您的 circumstances/conditions(table 统计数据、基数等)。
所以它会是这样的:
SELECT
...
FROM maintable mt
CROSS APPLY (
SELECT *
FROM table1
WHERE table1.itemid = mt.itemid
ORDER BY date DESC
fetch first 1 row only
)
CROSS APPLY (
SELECT *
FROM table2
WHERE table2.itemid = mt.itemid
ORDER BY date DESC
fetch first 1 row only
)
WHERE ...
PS。您没有指定您的 oracle 版本,所以我的回答是针对 Oracle 12+
我有一个包含一个主 table 和多个 history/log table 的数据库,用于存储主 table 的一些行的属性随时间的演变。这些属性并不存储在主table本身,而是必须从相关的history/logtable中查询。所有这些 table 都很大(以千兆字节为单位)。
我想转储整个主要 table 并加入所有 history/log table 的最后一个条目。
目前我通过子查询来实现,如下所示:
WITH
foo AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY date DESC) AS rownumber,
...
FROM table1),
bar AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY date DESC) AS rownumber,
...
FROM table2)
SELECT
...
FROM maintable mt
JOIN foo foo ON foo.itemid = mt.itemid AND foo.rownumber = 1
JOIN bar bar ON foo.itemid = mt.itemid AND bar.rownumber = 1
WHERE ...
问题是这很慢。这个问题有更快的解决方案吗?
我只能对该数据库执行只读查询:我不能对其进行任何更改。
在实际的Oracle版本中,通常使用laterals/CROSS APPLY会更好,因为CBO(oracle cost-based优化器)可以转换它们(DCL - lateral view decorrelation
转换)并使用优化连接方法取决于您的 circumstances/conditions(table 统计数据、基数等)。
所以它会是这样的:
SELECT
...
FROM maintable mt
CROSS APPLY (
SELECT *
FROM table1
WHERE table1.itemid = mt.itemid
ORDER BY date DESC
fetch first 1 row only
)
CROSS APPLY (
SELECT *
FROM table2
WHERE table2.itemid = mt.itemid
ORDER BY date DESC
fetch first 1 row only
)
WHERE ...
PS。您没有指定您的 oracle 版本,所以我的回答是针对 Oracle 12+