gpt4 book ai didi

sql - 范围分区跳过检查

转载 作者:行者123 更新时间:2023-12-01 13:54:26 25 4
gpt4 key购买 nike

我们在 oracle 中使用范围分区将大量数据按年份值进行分区。我们使用了范围分区,但每个分区只包含一年的数据。当我们编写针对特定年份的查询时,oracle 会从该分区获取信息,但仍会检查年份是否是我们指定的年份。由于今年列不是索引的一部分,因此它从表中获取年份并进行比较。我们已经看到,任何时候查询去获取表数据都变得太慢了。

我们能否以某种方式避免 oracle 比较年份值,因为我们肯定知道分区只包含一年的信息。

更新:

  1. 分区的年份数据类型为number类型。

  2. 我们没有选择任何额外的列。我只是在执行 count(*),没有选择任何列。

  3. 如果我们删除条件并将查询定位到特定分区select count(*) from table_name partition(part_2004)速度更快尽管从表中选择计数(*)
    其中 year = 2004
    慢得多。

  4. 分区在年份列上,它是一个数字,完成如下所示

    小于 2005 part_2004 的年份

    小于 2006 part_2005 的年份

    小于 2007 part_2006 的年份

……等等

最佳答案

如果没有解释计划或表定义,就很难判断发生了什么。我的第一个猜测是您有没有 year 列的 LOCAL 分区索引。它们有助于分区上的 COUNT(*),但是当您查询单个年份时(至少在 10.2.0.3 上)似乎不会使用它们。

这是一个重现您的发现(和解决方法)的小示例:

SQL> CREATE TABLE DATA (
2 YEAR NUMBER NOT NULL,
3 ID NUMBER NOT NULL,
4 extra CHAR(1000)
5 ) PARTITION BY RANGE (YEAR) (
6 PARTITION part1 VALUES LESS THAN (2010),
7 PARTITION part2 VALUES LESS THAN (2011)
8 );
Table created

SQL> CREATE INDEX ix_id ON DATA (ID) LOCAL;
Index created

SQL> INSERT INTO DATA
2 (SELECT 2009+MOD(ROWNUM, 2), ROWNUM, 'A' FROM DUAL CONNECT BY LEVEL <=1e4);

10000 rows inserted

SQL> EXEC dbms_stats.gather_table_stats(USER, 'DATA', CASCADE=>TRUE);

PL/SQL procedure successfully completed

现在比较两个解释计划:

SQL> SELECT COUNT(*) FROM DATA WHERE YEAR=2010;

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=197 Card=1 Bytes=4)
1 0 SORT (AGGREGATE)
2 1 PARTITION RANGE (SINGLE) (Cost=197 Card=5000 Bytes=20000)
3 2 TABLE ACCESS (FULL) OF 'DATA' (TABLE) (Cost=197 Card=5000...)

SQL> SELECT COUNT(*) FROM DATA PARTITION (part1);

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=11 Card=1)
1 0 SORT (AGGREGATE)
2 1 PARTITION RANGE (SINGLE) (Cost=11 Card=5000)
3 2 INDEX (FULL SCAN) OF 'IX_ID' (INDEX) (Cost=11 Card=5000)

如您所见,直接查询年份时使用索引。当您将年份添加到 LOCAL 索引时,它将被使用。我使用 COMPRESS 1 指令告诉 Oracle 压缩第一列。生成的索引与原始索引的大小几乎相同(由于压缩),因此性能应该不会受到影响。

SQL> DROP INDEX ix_id;
Index dropped

SQL> CREATE INDEX ix_id ON DATA (year, ID) LOCAL COMPRESS 1;
Index created

SQL> SELECT COUNT(*) FROM DATA WHERE YEAR=2010;

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=12 Card=1 Bytes=4)
1 0 SORT (AGGREGATE)
2 1 PARTITION RANGE (SINGLE) (Cost=12 Card=5000 Bytes=20000)
3 2 INDEX (RANGE SCAN) OF 'IX_ID' (INDEX) (Cost=12 Card=5000...)

关于sql - 范围分区跳过检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2535908/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com