多个分区子查询的性能

Posted

技术标签:

【中文标题】多个分区子查询的性能【英文标题】:Performance for multiple partitioned subqueries 【发布时间】:2020-09-15 13:23:49 【问题描述】:

我有一个数据库,其中包含一个主表和多个历史/日志表,这些表存储了主表中某些行的属性随时间的演变。这些属性不存储在主表本身,但必须从相关的历史/日志表中查询。所有这些表都很大(以千兆字节为单位)。

我想转储整个主表并加入所有历史/日志表的最后一个条目。

目前我通过如下子查询来完成:

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 ...

问题是这非常慢。这个问题有更快的解决方案吗?

我只能对此数据库执行只读查询:我不能对其进行任何更改。

【问题讨论】:

您可以为此查询运行解释计划,这应该会告诉您最高成本在哪里:blogs.oracle.com/oraclemagazine/how-to-read-an-execution-plan 第二次请求显示您的解释计划/DBMS_XPLAN 输出。此外,平均而言,每个不同的 item_id 有多少历史记录行?表的相对大小是多少(例如,历史记录是否比主表大 2 倍?10 倍?100 倍?) 【参考方案1】:

在实际的 Oracle 版本中,通常最好使用横向/交叉应用,因为 CBO(基于成本的 Oracle 优化器)可以转换它们(DCL - lateral view decorrelation 转换)并根据您的情况/条件使用最佳连接方法(表统计数据、基数等)。

所以应该是这样的:

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 ...

附言。你没有指定你的oracle版本,所以我的答案是Oracle 12+

【讨论】:

以上是关于多个分区子查询的性能的主要内容,如果未能解决你的问题,请参考以下文章

在子查询中聚合按位或*分区*?

Bigquery 将子查询应用于分区时间

hive UNION和子查询

Python中的子查询

表连接查询与where后使用子查询的性能分析。

ORA-01427:单行子查询返回多个行