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

V$SQL_SHARED_CURSOR TOP_LEVEL_RPI_CURSOR

Saya bekerja dengan seorang individu pada sebuah pertanyaan di forum MOSC baru-baru ini di mana mereka bertanya tentang kolom TOP_LEVEL_RPI_CURSOR dari tampilan V$SQL_SHARED_CURSOR. Ada sedikit dokumentasi tentang apa yang coba disampaikan kolom ini kepada DBA.

Semua dokumen Oracle katakan adalah bahwa kolom ini berisi "(Y|N) Adalah kursor RPI tingkat atas". Jadi apa artinya?

Saya akan menganggap pembaca posting ini akrab dengan kursor anak. Itu akan menghemat banyak informasi pengantar. Tampilan V$SQL_SHARED_CURSOR akan memberi tahu DBA mengapa kursor anak dan induknya memiliki versi yang berbeda di Kumpulan Bersama. Jika kolom OPTIMIZER_MISMATCH kursor anak berisi 'Y' dalam tampilan ini, maka sesi yang mengeksekusi kursor memiliki setelan pengoptimal yang berbeda dari sesi yang bertanggung jawab atas eksekusi kursor induk.

Jadi apa artinya ketika TOP_LEVEL_RPI_CURSOR diatur ke Y untuk seorang anak? Dokumentasinya tidak jelas. MOS memiliki sangat sedikit pada subjek. Dan semua hit Google saya di kolom ini cukup banyak hanya memuntahkan dokumentasi. Untuk mengetahui alasannya, ada baiknya mengetahui bahwa RPI adalah singkatan dari Recursive Program Interface. Ini adalah bagian dari kernel Oracle yang berhubungan dengan SQL rekursif. Dalam kasus kami, ini berkaitan dengan fakta bahwa pernyataan SQL dikeluarkan pada "kedalaman" yang berbeda.

Apa itu SQL rekursif? Ini adalah SQL yang dikeluarkan atas nama Anda, yang berarti pada kedalaman yang berbeda seperti yang akan saya ilustrasikan. Pertama, Oracle melakukan SQL rekursif sepanjang waktu. Pada tingkat dasar, ketika Anda mengeluarkan "pilih * dari nama_tabel", Oracle menanyakan Kamus Data untuk memastikan objek itu ada dan bahwa Anda memiliki izin pada tabel itu. Bagaimana Oracle melakukannya? Ini menggunakan pernyataan SQL lainnya. Pernyataan yang Anda keluarkan berada di level 0, level dasar. Ketika Oracle mengeluarkan pernyataan SQL untuk memeriksa apakah tabel itu ada, itu akan berada di level berikutnya, level 1. Terkadang, itu akan menyebabkan pernyataan SQL lain dikeluarkan di level berikutnya, level 2.

Kedalaman pernyataan SQL tidak terbatas pada apa yang dilakukan Oracle di latar belakang, atas nama Anda. Pertimbangkan saat Anda menjalankan prosedur tersimpan. Panggilan Anda ke prosedur tersimpan berada di kedalaman 0. Setiap pernyataan SQL dalam prosedur tersimpan berada di kedalaman 1. Jika prosedur tersimpan itu memanggil prosedur lain, SQL di prosedur lain akan berada di kedalaman 2.

Saya menggunakan informasi ini tentang SQL rekursif dan kedalaman SQL untuk membuat contoh sederhana di database Oracle 12.1.0.2 saya. Pertama, saya membuat prosedur tersimpan.

create or replace procedure my_sysdate 
as 
 v_dt date;
begin
 select sysdate into v_dt from dual;
end;
/

Saya kemudian menjalankan sesi SQL*Plus dan memulai pelacakan. Saya mengeluarkan pernyataan SQL yang sama dan kemudian saya memanggil prosedur saya.

SQL> alter session set sql_trace=true;
Session altered.
SQL> SELECT SYSDATE FROM DUAL
 2 /
SYSDATE
---------
05-APR-16
SQL> exec my_sysdate;
PL/SQL procedure successfully completed.
SQL> exit

Ketika saya memeriksa file jejak mentah, saya menemukan dua panggilan ke SYSDATE dari DUAL sebagai berikut:

PARSING DALAM KURSOR #140670990815296 len=24 dep=0 uid=9449 okt=3 tutup=9449 tim=24905125014484 hv=124468195 ad='81477be0′ sqlid='c749bc43qqfz3′ SELECT SYSDATE FROM DUAL

PARSING DALAM KURSOR #140670907623848 len=24 dep=1 uid=9449 okt=3 tutup=9449 tim=24905129780963 hv=124468195 ad='81477be0′ sqlid='c749bc43qqfz3′ SELECT SYSDATE FROM DUAL

Jika Anda melihat file jejak dengan cermat, Anda akan melihat bahwa yang kedua di depth=1 adalah akibat langsung dari prosedur tersimpan. Perhatikan bahwa meskipun prosedur tersimpan saya didefinisikan dalam semua huruf kecil, SQL yang dikeluarkan pada depth=1 dalam semua huruf besar. Akibatnya, ketika saya mengeluarkan pernyataan SQL yang sama secara langsung di sesi SQL*Plus saya (pada kedalaman=0), saya harus menggunakan bentuk huruf besar yang sama dari pernyataan itu sehingga akan memiliki nilai ID SQL yang sama.

File jejak juga menunjukkan ID SQL. Sekarang saya dapat meminta V$SQL_SHARED_CURSOR untuk nilai ID SQL tersebut dan menunjukkan bahwa TOP_LEVEL_RPI_CURSOR disetel untuk anak.

SQL> select sql_id,top_level_rpi_cursor from v$sql_shared_cursor where sql_id='c749bc43qqfz3';
SQL_ID T
------------- -
c749bc43qqfz3 N
c749bc43qqfz3 Y

Jadi di sana kami memiliki bukti kami. Satu-satunya perbedaan antara kedua kursor ini adalah bahwa satu adalah kedalaman dari mana mereka dieksekusi. Saya tidak yakin mengapa Oracle membutuhkan perbedaan ini di Shared Pool. Jika ada yang tahu, beri tahu saya.

Biasanya, kami tidak peduli dengan beberapa versi tambahan, beberapa kursor anak untuk ID SQL yang diberikan. Jika pernyataan SQL Anda memiliki jumlah versi yang tinggi, maka itu mungkin bukan karena tingkat kedalaman yang berbeda. Alasan lain akan lebih relevan dengan mengapa pernyataan SQL akan memiliki jumlah kursor anak yang tinggi, sejumlah besar versi yang berbeda. Tapi ini menjawab pertanyaan tentang apa yang dikatakan kolom itu kepada kita.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. LN() Fungsi di Oracle

  2. GROUP BY tanpa fungsi agregat

  3. LOG() Fungsi di Oracle

  4. Mengapa saya tidak dapat menggunakan variabel bind dalam pernyataan DDL/SCL dalam SQL dinamis?

  5. dbms_metadata.get_ddl tidak berfungsi