Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Sprawdzanie pominięcia partycji zakresu

Bez planu wyjaśnień lub definicji tabeli naprawdę trudno powiedzieć, co się dzieje. Moje pierwsze przypuszczenie jest takie, że masz indeksy partycjonowane LOKALNIE bez year kolumna. Pomagają z COUNT(*) na partycji, jednak wydaje się, że nie są używane przy zapytaniu o jeden rok (przynajmniej w 10.2.0.3).

Oto mały przykład, który odtwarza twoje odkrycie (i obejście):

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

Teraz porównaj dwa plany wyjaśnień:

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 widać, indeks nie używane przy bezpośrednim zapytaniu o rok. Po dodaniu roku do indeksu LOCAL będzie on używany. Użyłem instrukcji COMPRESS 1, aby powiedzieć Oracle, aby skompresować pierwszą kolumnę. Wynikowy indeks ma prawie taki sam rozmiar jak oryginalny indeks (dzięki kompresji), więc nie powinno to mieć wpływu na wydajność.

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. connect by klauzula w regex_substr

  2. jak obliczyć zakresy w Oracle

  3. XMLTABLE w oracle - Niezgodność typu dynamicznego XQuery:oczekiwana sekwencja singletona - uzyskano sekwencję wieloelementową

  4. Samouczek dotyczący formularzy i raportów Oracle 9i, Oracle 10g i Oracle 11g Developer Suite

  5. Oracle :konkatenacja ciągów jest za długa