oracle sql 12c 可以绕过分区吗?
Can partitioning be bypassed in oracle sql 12c?
我有一个 table,其中约 2500 万行按时间键(月)分区。每个分区内大约有 20 万行。
我们在 BI 上下文中使用此 table,这意味着业务用户对此 table 的查询与除过滤器值之外的查询始终相同。
终端用户大多查询24个月的数据范围,也就是说需要24个分区来查找数据。我们认为,如果我们在没有分区的情况下查询相同的 table,则查询比在分区的 table 上查询要快得多。因此我们认为,当查看太多(在本例中为 24 个)分区时,分区的 table 并不是那么有趣。
是否有一些参数(改变会话...)或提示我们可以用来不让优化器使用分区而是以另一种方式扫描 table?
每个分区都有自己的段。因此,数据库在物理上将每个行存储在不同的位置。假设您需要访问 table,您必须读取所有相关分区。
所以不,你不能"ignore"或绕过分区。
而且也没有办法取消 table 的分区。您必须重新创建它,最好使用 dbms_redefinition 来完成。
或者您可以将分区合并在一起:
create table t (
c1, c2, c3, c4
) partition by range ( c1 ) (
partition p0 values less than ( 10 ),
partition p1 values less than ( 20 ),
partition p2 values less than ( 30 ),
partition p3 values less than ( 40 ),
partition p4 values less than ( 50 )
) as
select level c1, sysdate + level c2 ,
round ( dbms_random.value ( 1, 100 ) ) c3,
dbms_random.string ( 'a', 20 ) c4
from dual
connect by level < 50;
alter table t
merge partitions p0, p1, p2, p3, p4
into partition p4;
select partition_name
from user_tab_partitions
where table_name = 'T';
PARTITION_NAME
P4
当然,查询性能只是分区的原因之一。使用它还有很多其他原因,例如:
- 通过
drop/truncate partition
快速轻松地归档数据
- 使用
exchange partition
快速加载数据
- 通过将分区标记为
read only
来阻止人们更改旧数据
- 将较旧的数据存储在较慢(较便宜)的磁盘上
- ...
因此,在清除它们之前,请检查您是否没有使用其他分区功能。
就是说,~200k rows/partition 和 25M 的总容量似乎有点小,值得对我进行分区。
从技术上讲,还有另一种选择...
business users query on this table with queries that, apart from
filter values, are always the same.
这些是聚合(count、sum、avg 等)查询吗?例如:
select customer_id, count(*)
from ...
where ...
group by customer_id
如果是这样的话,物化视图 (MV) 可能是 "bypass" 分区的一个不错的选择。
create materialized view mv as
select customer_id, count(*)
from ...
where ...
group by customer_id
您可以使用与基础 table 不同的方式将它们分区(或不分区)。如果您的查询通常处理 "many" 行,但处理 return "few",那么使用 MV 的优势可能会快得多。
我有一个 table,其中约 2500 万行按时间键(月)分区。每个分区内大约有 20 万行。
我们在 BI 上下文中使用此 table,这意味着业务用户对此 table 的查询与除过滤器值之外的查询始终相同。
终端用户大多查询24个月的数据范围,也就是说需要24个分区来查找数据。我们认为,如果我们在没有分区的情况下查询相同的 table,则查询比在分区的 table 上查询要快得多。因此我们认为,当查看太多(在本例中为 24 个)分区时,分区的 table 并不是那么有趣。
是否有一些参数(改变会话...)或提示我们可以用来不让优化器使用分区而是以另一种方式扫描 table?
每个分区都有自己的段。因此,数据库在物理上将每个行存储在不同的位置。假设您需要访问 table,您必须读取所有相关分区。
所以不,你不能"ignore"或绕过分区。
而且也没有办法取消 table 的分区。您必须重新创建它,最好使用 dbms_redefinition 来完成。
或者您可以将分区合并在一起:
create table t (
c1, c2, c3, c4
) partition by range ( c1 ) (
partition p0 values less than ( 10 ),
partition p1 values less than ( 20 ),
partition p2 values less than ( 30 ),
partition p3 values less than ( 40 ),
partition p4 values less than ( 50 )
) as
select level c1, sysdate + level c2 ,
round ( dbms_random.value ( 1, 100 ) ) c3,
dbms_random.string ( 'a', 20 ) c4
from dual
connect by level < 50;
alter table t
merge partitions p0, p1, p2, p3, p4
into partition p4;
select partition_name
from user_tab_partitions
where table_name = 'T';
PARTITION_NAME
P4
当然,查询性能只是分区的原因之一。使用它还有很多其他原因,例如:
- 通过
drop/truncate partition
快速轻松地归档数据
- 使用
exchange partition
快速加载数据
- 通过将分区标记为
read only
来阻止人们更改旧数据
- 将较旧的数据存储在较慢(较便宜)的磁盘上
- ...
因此,在清除它们之前,请检查您是否没有使用其他分区功能。
就是说,~200k rows/partition 和 25M 的总容量似乎有点小,值得对我进行分区。
从技术上讲,还有另一种选择...
business users query on this table with queries that, apart from filter values, are always the same.
这些是聚合(count、sum、avg 等)查询吗?例如:
select customer_id, count(*)
from ...
where ...
group by customer_id
如果是这样的话,物化视图 (MV) 可能是 "bypass" 分区的一个不错的选择。
create materialized view mv as
select customer_id, count(*)
from ...
where ...
group by customer_id
您可以使用与基础 table 不同的方式将它们分区(或不分区)。如果您的查询通常处理 "many" 行,但处理 return "few",那么使用 MV 的优势可能会快得多。