If you have my book "expert one on one", I have a discussion on this and why pga memory in general won't go down (it would not be worth the effort -- it won't really "shrink" at the OS level regardless). We can "force it" but in general, you are only making yourself feel better but the system is running slower for it.
Here is an example, if you want the details, my book goes into why shrinking PGA memory in dedicated server isn't worth the effort:
ops$tkyte@ORA920.US.ORACLE.COM> declare
2 type array is table of varchar2(4000) index by binary_integer;
3
4 l_data array;
5
6 procedure show_pga_usage( p_msg in varchar2 )
7 is
8 begin
9 dbms_output.put_line( p_msg );
10 for x in ( select a.name, b.value
11 from v$statname a, v$mystat b
12 where a.statistic# = b.statistic#
13 and a.name like '%pga%' )
14 loop
15 dbms_output.put_line( to_char( x.value, '999,999,999' ) || ' ' || x.name );
16 end loop;
17 end;
18 begin
19 show_pga_usage( 'starting' );
20
21 for i in 1 .. 1000
22 loop
23 l_data(i) := rpad( '*', 4000, '*' );
24 end loop;
25 show_pga_usage( 'after filling array: ' );
26
27 for i in 1 .. l_data.count
28 loop
29 if ( mod( i, 500 ) = 0 )
30 then
31 show_pga_usage( 'after deleting ' || i || ' entries' );
32 end if;
33 l_data.delete(i);
34 end loop;
35 show_pga_usage( 'after deleting ALL entries' );
36 end;
37 /
starting
401,444 session pga memory
401,444 session pga memory max
after filling array:
5,888,396 session pga memory
5,888,396 session pga memory max
after deleting 500 entries
5,888,396 session pga memory
5,888,396 session pga memory max
after deleting 1000 entries
5,888,396 session pga memory
5,888,396 session pga memory max
after deleting ALL entries
5,888,396 session pga memory
5,888,396 session pga memory max
PL/SQL procedure successfully completed.
ops$tkyte@ORA920.US.ORACLE.COM> @mystat pga
ops$tkyte@ORA920.US.ORACLE.COM> select a.name, b.value
2 from v$statname a, v$mystat b
3 where a.statistic# = b.statistic#
4 and lower(a.name) like '%' || lower('&1')||'%'
5 --and b.value > 0
6 /
old 4: and lower(a.name) like '%' || lower('&1')||'%'
new 4: and lower(a.name) like '%' || lower('pga')||'%'
NAME VALUE
------------------------------ ----------
session pga memory 5888396
session pga memory max 5888396
ops$tkyte@ORA920.US.ORACLE.COM>
ops$tkyte@ORA920.US.ORACLE.COM> declare
2 type array is table of varchar2(4000) index by binary_integer;
3
4 l_data array;
5
6 procedure show_pga_usage( p_msg in varchar2 )
7 is
8 begin
9 dbms_output.put_line( p_msg );
10 for x in ( select a.name, b.value
11 from v$statname a, v$mystat b
12 where a.statistic# = b.statistic#
13 and a.name like '%pga%' )
14 loop
15 dbms_output.put_line( to_char( x.value, '999,999,999' ) || ' ' || x.name );
16 end loop;
17 end;
18 begin
19 show_pga_usage( 'starting' );
20
21 for i in 1 .. 1000
22 loop
23 l_data(i) := rpad( '*', 4000, '*' );
24 end loop;
25 show_pga_usage( 'after filling array: ' );
26
27 for i in 1 .. l_data.count
28 loop
29 if ( mod( i, 500 ) = 0 )
30 then
31 show_pga_usage( 'after deleting ' || i || ' entries' );
32 dbms_session.FREE_UNUSED_USER_MEMORY;
33 show_pga_usage( 'after deleting ' || i || ' entries and calling "free memory"' );
34 end if;
35 l_data.delete(i);
36 end loop;
37 show_pga_usage( 'after deleting ALL entries' );
38 end;
39 /
starting
5,888,396 session pga memory
5,888,396 session pga memory max
after filling array:
5,888,396 session pga memory
5,888,396 session pga memory max
after deleting 500 entries
5,888,396 session pga memory
5,888,396 session pga memory max
after deleting 500 entries and calling "free memory"
3,194,204 session pga memory
5,888,396 session pga memory max
after deleting 1000 entries
3,194,204 session pga memory
5,888,396 session pga memory max
after deleting 1000 entries and calling "free memory"
467,156 session pga memory
5,888,396 session pga memory max
after deleting ALL entries
467,156 session pga memory
5,888,396 session pga memory max
PL/SQL procedure successfully completed.