一次从多个分区中选择

Posted

技术标签:

【中文标题】一次从多个分区中选择【英文标题】:Select from several partitions at once 【发布时间】:2013-10-22 16:12:28 【问题描述】:

对不起,我的英语。 我有 2 个表,都按日期间隔分区,但在不同的字段上。 两个表中都有大量记录(每个分区约 100 kk)。 第一个表在快速磁盘表空间中保留它的 3 个最后(按日期)分区,其他分区在慢速磁盘表空间中。 我也有一些系统,它处理数据。它并行执行进程,每个进程通过 select 语句从第一个表中获取数据,并将处理后的数据放入第二个表中。 所以我只需要从“快速”(!)分区中选择第一个表中的数据,然后将其放入第二个表中。 但是第二个表在其他(日期也是)字段上分区。当进程并行执行时,当不同的进程试图将数据放入第二个表的同一分区时,我会遇到死锁。

好的解决方案是每个进程只从“快速”分区(但所有这些分区一次)只获取第二个表中一个分区的数据。在这种情况下,每个进程都会将数据推送到一个分区中。但我不知道该怎么做。

如果我做

select t.field1, t.field2 from (select * from FIRST_TABLE partition("P1") union all
select * from FIRST_TABLE partition("P2") union all
select * from FIRST_TABLE partition("P3")) t
where t.field3='someVal' --Indexed field in FIRST_TABLE 

OracleDB 是否会在 FIRST_TABLE 中的分区上使用本地索引来解析 where 子句?这种方式将如何影响性能?

有什么想法可以解决我的问题吗?

PS 关于如何在一个选择语句中从多个分区中选择数据有很多问题,但我没有找到对我的情况有用的答案。

【问题讨论】:

How does one do a SQL select over multiple partitions?的可能重复 【参考方案1】:

在查询分区表时,您几乎不想使用PARTITION 子句。您几乎总是希望指定一个谓词以允许 Oracle 自行进行分区修剪。

SELECT t.column1, t.column2
  FROM first_table t
 WHERE t.partitioned_date_column >= <<date that delimits fast partitions>>
   AND t.column3 = 'someVal'

当您在表分区的日期列上指定谓词时,Oracle 可以自动确定需要访问哪些分区。

【讨论】:

如果我需要将一个旧分区移动到快速表空间并重新处理数据怎么办(抱歉,我没有写过这个限制)?这种方式不允许定义单独的分区?不要一个接一个地铺设。 @Andrey - 我不确定这会如何改变任何事情。您仍然希望在partitioned_date_column 上指定一个谓词,以指定需要从哪些分区中读取。如果您说日期范围可能不连续,您可能需要几个 OR'd 在一起的谓词,而不是 &gt;=,或者您可能需要一个 IN 列表。 如果我写 AND( g.create_date &gt;= to_date('2013-09-01','yyyy-mm-dd') OR g.create_date &gt;= to_date('2013-06-01','yyyy-mm-dd') ) 它将占用 2013-06-01 之后的所有分区(因为它与条件有关),不是吗? @Andrey - 好吧,是的,如果你这样编码的话。例如,如果您想要 9/1 之后的所有内容以及 6/1 到 6/30 的所有内容,则您希望 OR 条件为 BETWEEN&gt;= date '2013-06-01' and &lt;= date '2013-06-30'。您的条件需要与您要处理的任何一组日期值相匹配。 这是由优化器引起的,如何从表中获取数据-从执行分区或全表扫描来检查条件?我如何检查在and( g.create_date between to_date('2013-09-01','yyyy-mm-dd') and add_months(to_date('2013-09-01','yyyy-mm-dd'),1) or g.create_date between to_date('2013-06-01','yyyy-mm-dd') and add_months(to_date('2013-06-01','yyyy-mm-dd'),1) ) 条件下,DB 仅使用我指定的分区?以某种方式使用慢速磁盘是不可接受的(性能至关重要)。对不起我的细致,我只想成为舒尔=)【参考方案2】:

如果您尝试自己并行执行三个查询,例如同时运行,您可能会遇到死锁:

insert into t2 select from t1 partition ("P1");

然后在另一个外壳/窗口/作业中:

insert into t2 select from t1 partition ("P2")

如果你查询

select *
from t1
where date_column_used_for_partition >= 3_dates_ago

Oracle 将只选择您需要的三个分区,您不需要使用UNION

通过这种方式,您可以将INSERT INTO... SELECT 语句放在一个查询中,并且您不必担心死锁,Oracle 引擎会知道它必须在第二个表的哪个分区中插入数据,他会为您管理插入。

【讨论】:

以上是关于一次从多个分区中选择的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server Management Studio 中从多维数据集中删除分区

选择排序

选择排序

java 选择排序与冒泡排序

直接选择排序

排序:直接选择排序