sql >> Database teknologi >  >> RDS >> Oracle

Overspringskontrol af rækkepartition

Uden forklaringsplanen eller tabeldefinitionen er det virkelig svært at sige, hvad der foregår. Mit første gæt er, at du har LOKALE partitionerede indekser uden year kolonne. De hjælper med COUNT(*) på en partition, men de ser ikke ud til at blive brugt, når du forespørger et enkelt år (i hvert fald den 10.2.0.3).

Her er et lille eksempel, der gengiver dit fund (og en løsning):

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

Sammenlign nu de to forklarende planer:

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)

Som du kan se, er indekset ikke bruges, når du forespørger året direkte. Når du tilføjer året til det LOKALE indeks, vil det blive brugt. Jeg brugte COMPRESS 1-instruktionen til at bede Oracle om at komprimere den første kolonne. Det resulterende indeks har næsten samme størrelse som det originale indeks (takket være komprimering), så ydeevnen bør ikke blive påvirket.

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. AES_ENCRYPT og AES_DECRYPT ved hjælp af java

  2. TIME_FORMAT() Eksempler – MySQL

  3. Betydningen af ​​basislinjer

  4. Vælg en optagelse baseret på metaen