Oracle
 sql >> база данни >  >> RDS >> Oracle

Проверка за пропускане на дял на диапазон

Без плана за обяснение или дефиницията на таблицата е наистина трудно да се каже какво се случва. Първото ми предположение е, че имате LOCAL разделени индекси без year колона. Те помагат с 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...)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ROracle dbWriteTable създава Oracle TIMESTAMP колони за R DATE колони

  2. Смесване на USING и ON в Oracle ANSI join

  3. Неподдържан тип данни на колона ODP.NET

  4. Oracle съхранява ли крайни нули за тип данни число?

  5. Връщане на параметри в изрази за вмъкване на Oracle SQL