Saya memiliki tabel dengan 250 ribu baris di basis data pengujian saya. (Ada beberapa ratus juta dalam produksi, kita dapat mengamati masalah yang sama di sana.) Tabel memiliki pengidentifikasi string nvarchar2 (50), bukan nol, dengan indeks unik di atasnya (bukan PK).
Pengidentifikasi terdiri dari bagian pertama yang memiliki 8 nilai berbeda di basis data pengujian saya (dan sekitar seribu dalam produksi), kemudian tanda @, dan akhirnya angka, 1 hingga 6 digit. Misalnya mungkin ada 50 ribu baris yang dimulai dengan 'ABCD_BGX1741F_2006_13_20110808.xml @', dan diikuti oleh 50 ribu angka yang berbeda.
Ketika saya meminta satu baris berdasarkan pengenalnya, kardinalitas diperkirakan 1, biayanya sangat rendah, itu berfungsi dengan baik. Ketika saya meminta lebih dari satu baris dengan beberapa pengidentifikasi dalam ekspresi IN atau ekspresi OR, estimasi untuk indeks benar-benar salah, sehingga pemindaian tabel penuh digunakan. Jika saya memaksakan indeks dengan petunjuk, itu sangat cepat, pemindaian tabel penuh sebenarnya dieksekusi urutan besarnya lebih lambat (dan lebih banyak lebih lambat dalam produksi). Jadi ini adalah masalah pengoptimal.
Sebagai tes, saya menduplikasi tabel (dalam skema yang sama + tablespace) dengan DDL yang sama persis dan konten yang sama persis. Saya menciptakan kembali indeks unik di tabel pertama untuk ukuran yang baik, dan membuat indeks yang sama persis di tabel klon. Saya melakukan DBMS_STATS.GATHER_SCHEMA_STATS('schemaname',estimate_percent=>100,cascade=>true);
. Anda bahkan dapat melihat bahwa nama indeks berurutan. Jadi sekarang satu-satunya perbedaan antara dua tabel adalah bahwa yang pertama dimuat secara acak selama periode waktu yang lama, dengan blok yang tersebar di disk (dalam tablespace bersama dengan beberapa tabel besar lainnya), yang kedua dimuat sebagai satu batch INSERT-SELECT. Selain itu, saya tidak bisa membayangkan perbedaan apa pun. (Tabel asli telah menyusut sejak penghapusan besar terakhir, dan tidak ada satu penghapusan pun setelah itu.)
Berikut adalah rencana permintaan untuk orang sakit dan tabel klon (String di bawah kuas hitam sama di seluruh gambar, dan juga di bawah kuas abu-abu.):
(Dalam contoh ini, ada 1867 baris yang dimulai dengan pengenal yang disikat hitam. Kueri 2-baris menghasilkan kardinalitas 1867 * 2, kueri 3-baris menghasilkan kardinalitas 1867 * 3, dll. Tidak dapat secara kebetulan, Oracle tampaknya tidak peduli dengan akhir dari pengidentifikasi.)
Apa yang bisa menyebabkan perilaku ini? Jelas akan sangat mahal untuk membuat ulang tabel dalam produksi.
USER_TABLES: http://i.stack.imgur.com/nDWze.jpg USER_INDEXES: http://i.stack.imgur.com/DG9um.jpg Saya hanya mengubah nama skema dan tablespace. Anda dapat melihat bahwa tabel dan nama indeks sama seperti pada tangkapan layar rencana kueri.