sql >> Database >  >> RDS >> Oracle

Controle van bereikpartitie overslaan

Zonder het uitlegplan of de tabeldefinitie is het echt moeilijk te zeggen wat er aan de hand is. Mijn eerste gok is dat je LOKALE gepartitioneerde indexen hebt zonder het year kolom. Ze helpen met de COUNT(*) op een partitie, maar ze lijken niet te worden gebruikt wanneer je een enkel jaar opvraagt ​​(tenminste op 10.2.0.3).

Hier is een klein voorbeeld dat uw bevinding reproduceert (en een tijdelijke oplossing):

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

Vergelijk nu de twee uitlegplannen:

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)

Zoals je kunt zien is de index niet gebruikt wanneer u het jaar rechtstreeks opvraagt. Wanneer u het jaar toevoegt aan de LOKALE index, wordt deze gebruikt. Ik heb de COMPRESS 1-instructie gebruikt om Oracle te vertellen de eerste kolom te comprimeren. De resulterende index is bijna even groot als de oorspronkelijke index (dankzij compressie), dus de prestaties mogen niet worden beïnvloed.

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. MySQL toetreden en uitsluiten?

  2. Geen toegang tot Sonar MySQL-database Veroorzaakt door:java.sql.SQLException:Toegang geweigerd voor gebruiker 'sonar'@'glassfishdev.ccs.local' (met wachtwoord:JA)

  3. Zijn een CASE-statement en een DECODE equivalent?

  4. ListView-besturing Drag Drop Gebeurtenissenafhandeling