sql >> Databáze >  >> RDS >> Oracle

Kontrola přeskočení oddílu rozsahu

Bez plánu vysvětlení nebo definice tabulky je opravdu těžké říct, co se děje. Můj první odhad je, že máte LOCAL rozdělené indexy bez year sloupec. Pomáhají s COUNT(*) na oddílu, ale zdá se, že se nepoužívají, když se dotazujete na jeden rok (alespoň na 10.2.0.3).

Zde je malý příklad, který reprodukuje vaše zjištění (a řešení):

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

Nyní porovnejte dva vysvětlující plány:

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)

Jak vidíte, index není používá se při přímém dotazu na rok. Když do LOCAL indexu přidáte rok, bude použit. Použil jsem instrukci COMPRESS 1, abych řekl Oracle, aby komprimoval první sloupec. Výsledný index má téměř stejnou velikost jako původní index (díky kompresi), takže výkon by neměl být ovlivněn.

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. Testování databázových jednotek Android SQLite

  2. Mohu si být jistý posledním ID vložení Mysql?

  3. Získat nejbližší zeměpisnou délku a šířku z databázové tabulky MSSQL?

  4. Propojení Google Cloud SQL s Wordpress na Google Compute Engine