Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Pemeriksaan lewati partisi rentang

Tanpa rencana penjelasan atau definisi tabel, sangat sulit untuk mengatakan apa yang terjadi. Tebakan pertama saya adalah Anda memiliki indeks yang dipartisi LOCAL tanpa year kolom. Mereka membantu dengan COUNT(*) pada sebuah partisi, namun mereka tampaknya tidak digunakan ketika Anda menanyakan satu tahun (setidaknya pada 10.2.0.3).

Berikut adalah contoh kecil yang mereproduksi temuan Anda (dan solusinya):

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

Sekarang bandingkan keduanya, jelaskan rencana:

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)

Seperti yang Anda lihat, indeksnya tidak digunakan saat Anda menanyakan tahun secara langsung. Saat Anda menambahkan tahun ke indeks LOKAL, itu akan digunakan. Saya menggunakan instruksi KOMPRES 1 untuk memberi tahu Oracle untuk mengompres kolom pertama. Indeks yang dihasilkan berukuran hampir sama dengan indeks asli (berkat kompresi) sehingga kinerja tidak akan terpengaruh.

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. Bagaimana cara mendapatkan tanggal efektif saat ini di Oracle?

  2. Memanggil kode paket PL/SQL dalam Program Java

  3. Navigasi dari App A ke App B dengan kredensial yang sama - APEX 19.2

  4. ambil hasil dari kueri

  5. ORA-01036:nama/nomor variabel ilegal saat memanggil fungsi tersimpan