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

Bagaimana Oracle memproses panggilan fungsi tersimpan dalam SQL?

Pertanyaan yang sangat bagus.

Saya pertama kali mencoba membuat tabel dan memasukkan data sampel (hanya lima baris):

create table my_table(value number);
insert into my_table(value) values(1);
insert into my_table(value) values(2);
insert into my_table(value) values(3);
insert into my_table(value) values(4);
insert into my_table(value) values(5);

Saya membuat paket pengujian sederhana untuk menguji ini.

create or replace package my_package is
  g_counter_SELECT PLS_INTEGER := 0; -- counter for SELECT statement
  g_counter_WHERE  PLS_INTEGER := 0; -- counter for WHERE clause
  function my_function(number_in in number, type_in in varchar2) return number;
  procedure reset_counter;
end;
/

Dan tubuh...

create or replace package body my_package is
  function my_function(number_in in number, type_in in varchar2) return number is
  begin
    IF(type_in = 'SELECT') THEN
        g_counter_SELECT := g_counter_SELECT + 1;
    ELSIF(type_in = 'WHERE') THEN
        g_counter_WHERE := g_counter_WHERE + 1;
    END IF;
    return mod(number_in, 2);
  end;
  procedure reset_counter is
  begin
    g_counter_SELECT := 0;
    g_counter_WHERE := 0;
  end;
end;
/

Sekarang, kita dapat menjalankan tes pada Oracle 9i (pada 11g adalah hasil yang sama):

-- reset counter
exec my_package.reset_counter();

-- run query
select t.value, my_package.my_function(t.value, 'SELECT')
  from my_table t
 where my_package.my_function(t.value, 'WHERE') = 1;

-- print result
exec dbms_output.put_line('Count (SELECT) = ' || my_package.g_counter_SELECT);
exec dbms_output.put_line('Count (WHERE) = ' || my_package.g_counter_WHERE);

Hasilnya adalah:

DBMS Output (Session: [1] [email protected] at: 08.09.2010 01:50:04): 
-----------------------------------------------------------------------
Count (SELECT) = 3
Count (WHERE) = 5

Berikut adalah tabel rencana:

--------------------------------------------------------------------
| Id  | Operation            |  Name       | Rows  | Bytes | Cost  |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |       |       |       |
|*  1 |  TABLE ACCESS FULL   | MY_TABLE    |       |       |       |
--------------------------------------------------------------------

Yang berarti bahwa fungsi (di WHERE calues) dipanggil untuk setiap baris tabel (dalam kasus FULL TABLE SCAN). Dalam pernyataan SELECT diluncurkan beberapa kali sesuai dengan kondisi WHERE my_function =1

Sekarang... uji kueri kedua Anda (hasil yang sama pada Oracle9i dan 11g)

Hasilnya adalah:

DBMS Output (Session: [1] [email protected] at: 08.09.2010 02:08:04): 
-----------------------------------------------------------------------
Count (SELECT) = 8
Count (WHERE) = 0

Jelaskan tampilan polos seperti ini (untuk mode PILIH pengoptimal):

--------------------------------------------------------------------
| Id  | Operation            |  Name       | Rows  | Bytes | Cost  |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |       |       |       |
|*  1 |  TABLE ACCESS FULL   | MY_TABLE    |       |       |       |
--------------------------------------------------------------------

PERTANYAANNYA ADALAH:Mengapa Hitungan (PILIH) =8?

Karena Oracle pertama kali menjalankan subquery (dalam kasus saya dengan FULL TABLE SCAN, 5 baris =5 panggilan my_function dalam pernyataan SELECT):

select t.value, my_package.my_function(t.value, 'SELECT') func_value from my_table t

Dan untuk view ini (subquery seperti view) dijalankan 3 kali (karena kondisi subquery.func_value =1) panggil lagi function my_function.

Secara pribadi tidak merekomendasikan untuk menggunakan fungsi dalam klausa WHERE, tetapi saya akui bahwa terkadang ini tidak dapat dihindari.

Sebagai contoh terburuk dari hal ini diilustrasikan sebagai berikut:

select t.value, my_package.my_function(t.value, 'SELECT')
  from my_table t
 where my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE')
   and my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE')
   and my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE')
   and my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE')
   and my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE');

Di mana hasil pada Oracle 9i berada :

Count (SELECT) = 5
Count (WHERE) = 50

Dan pada Oracle 11g adalah :

Count (SELECT) = 5
Count (WHERE) = 5

Yang dalam hal ini menunjukkan bahwa terkadang penggunaan fungsi mungkin penting untuk kinerja. Dalam kasus lain (11g) ia memecahkan database itu sendiri.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menghubungkan ke Oracle DB jarak jauh dengan Nodejs melalui Oracledb Driver

  2. Oracle - Gabung luar kiri dengan klausa where

  3. Cara mendekati Got minus satu dari kesalahan panggilan baca saat menghubungkan ke instans Oracle RDS Amazon

  4. Jaring Pengaman

  5. bagaimana mengganti huruf beraksen di kolom varchar2 di oracle