I have an application running against a 10g database (10.2.0.1.0 on SPARC Solaris 10), and am trying to investigate one particular SQL statement with poor performance. I know the SQL statement (an UPDATE) - I just want to get the execution plan used when it is executed by the application. By looking in V$SQL I can see that the SQL statement appears, and I can see that the EXECUTIONS count goes up over time. I also see which CHILD of that SQL it is. However, when I try to get the execution plan by calling DBMS_XPLAN.DISPLAY_CURSOR I get the message that:
NOTE: cannot fetch plan for SQL_ID: aaaaaaaaaaaa, CHILD_NUMBER: 1
Please verify value of SQL_ID and CHILD_NUMBER;
It could also be that the plan is no longer in cursor cache (check v$sql_plan)
Checking V$SQL_PLAN there is indeed nothing for that SQL_ID and CHILD_NUMBER.
My main question is, why is the SQL execution plan being removed or reused or whatever from the library cache in the shared pool so quickly, when it has only just been executed in the last minute or so? What can I do to keep the execution plan in the shared pool long enough that I can grab it and see what it was?
The SQL statement is an UPDATE and uses bind variables throughout. The SQL_ID is the same in all cases, indicating that it is indeed the same SQL statement each time. I do not think that query rewriting is taking place - cursor_sharing is EXACT. So I do believe that the SQL does really contain the bind variables.
Sometimes when I query V$SQL a little later on the previous CHILD has disappeared and a new CHILD has appeared, for the same SQL UPDATE on the same SQL_ID.
I know I could trace the session to get all SQL statements, but getting the execution plan using DBMS_XPLAN seems the most direct and logical way to go about it. I'd also like to understand why this whole behaviour is occurring.
I also have some follow on questions:
What use is the shared pool if it ages out such SQL execution plans so quickly? The next execution is going to have to re-parse and optimize it all over again. Okay maybe not re-parse depending on things, but certainly re-optimize. Won't it? I guess this could happen if the shared pool was too small, but the SGA is 2.5 GB (sga_target), and the shared pool shows free memory - currently 41 MB of a shared pool of 450 MB (from V$SGASTAT, and 1.9 GB for buffer cache). How do I prove if it is the shared pool size or something else? Unfortunately Oracle now has so many other things in the shared pool, apart from the library cache (again, see V$SGASTAT for the individual allocations), that more and more is used within it by other things.
Why am I seeing multiple children (CHILD_NUMBER) of the same SQL statement? I know of some reasons why this can occur e.g. different schemas and tables, but I am pretty sure that this is all the same SQL statement on the same table in the same schema. But to be honest, Yes, we do have multiple schemas in the same database, so it could be related to this. But I am pretty sure that no one else is running the same application at the same time. So all of these UPDATEs should be due to my session. Are the multiple children related to the re-optimization of the SQL because of the execution plan being removed? My concern is that these new CHILDREN suddenly appear after the application has been running for a while, and are clearly due to the same application and same session issuing the same SQL again, some time later on.
The whole point of the library cache of SQL statements is to reuse execution plans. This both avoids the effort of producing another execution plan, and ensures that all executions use the same execution plan. But the appearance of these different children surely mean that they have been parsed and optimized separately, and that they could be using a different execution plan. Which may mean that the execution plans are radically different, and something I want to avoid. I want one good execution plan to be reliably used every time this SQL is executed.
Many Thanks,
John