I made a new graph in my PythonDBAGraphs program. Here is an example with real data but the database name blanked out:
My graphs are all sized for 1920 x 1080 monitors so I can see all the detail in the lines using my entire screen. The idea for this graph is to show how the performance of the queries that matter to the users changes as we add more load and data to this production database. I knew that this database had many queries with literals in their where clauses. I decided to pick a group of SQL by FORCE_MATCHING_SIGNATURE and to graph the average elapsed run time against the total number of executions.
I used this query to list all the SQL by signature:
column FORCE_MATCHING_SIGNATURE format 99999999999999999999 select FORCE_MATCHING_SIGNATURE, sum(ELAPSED_TIME_DELTA)/1000000 total_seconds, sum(executions_delta) total_executions, count(distinct sql_id) number_sqlids, count(distinct snap_id) number_hours, min(PARSING_SCHEMA_NAME) from DBA_HIST_SQLSTAT group by FORCE_MATCHING_SIGNATURE order by number_hours desc;
This is an edited version of the output – cut down to fit the page:
FORCE_MATCHING_SIGNATURE TOTAL_SECONDS TOTAL_EXECUTIONS NUMBER_HOURS ------------------------ ------------- ---------------- ------------ 14038313233049026256 22621.203 68687024 1019 18385146879684525921 18020.9776 157888956 1013 2974462313782736551 22875.4743 673687 993 12492389898598272683 6203.78985 66412941 992 14164303807833460050 4390.32324 198997 980 10252833433610975622 6166.07675 306373 979 17697983043057986874 17391.0907 25914398 974 15459941437096211273 9869.31961 7752698 967 2690518030862682918 15308.8561 5083672 952 1852474737868084795 50095.5382 3906220 948 6256114255890028779 380.095915 4543306 947 16226347765919129545 9199.14289 215756 946 13558933806438570935 394.913411 4121336 945 12227994223267192558 369.784714 3970052 945 18298186003132032869 296.887075 3527130 945 17898820371160082776 184.125159 3527322 944 10790121820101128903 2474.15195 4923888 943 2308739084210563004 265.395538 3839998 941 13580764457377834041 2807.68503 62923457 934 12635549236735416450 1023.42959 702076 918 17930064579773119626 2423.03972 61576984 914 14879486686694324607 33.253284 17969 899 9212708781170196788 7292.5267 126641 899 357347690345658614 6321.51612 182371 899 15436428048766097389 11986.082 334125 886 5089204714765300123 6858.98913 190700 851 11165399311873161545 4864.60469 45897756 837 12042794039346605265 11223.0792 179064 835 15927676903549361476 505.624771 3717196 832 9120348263769454156 12953.0746 230090 828 10517599934976061598 311.61394 3751259 813 6987137087681155918 540.565595 3504784 809 11181311136166944889 5018.309 59540417 808 187803040686893225 3199.87327 12788206 800
I picked the ones that had executed in 800 or more hours. Our AWR has about 1000 hours of history so 800 hours represents about 80% of the AWR snapshots. I ended up pulling one of these queries out because it was a select for update and sometimes gets hung on row locks and skews the graph. So, the graph above has that one pulled out.
I based the graph above on this query:
select sn.END_INTERVAL_TIME, sum(ss.executions_delta) total_executions, sum(ELAPSED_TIME_DELTA)/((sum(executions_delta)+1)) from DBA_HIST_SQLSTAT ss,DBA_HIST_SNAPSHOT sn where ss.snap_id=sn.snap_id and ss.INSTANCE_NUMBER=sn.INSTANCE_NUMBER and ss.FORCE_MATCHING_SIGNATURE in ( 14038313233049026256, 18385146879684525921, 2974462313782736551, 12492389898598272683, 14164303807833460050, 10252833433610975622, 17697983043057986874, 15459941437096211273, 2690518030862682918, 6256114255890028779, 16226347765919129545, 13558933806438570935, 12227994223267192558, 18298186003132032869, 17898820371160082776, 10790121820101128903, 2308739084210563004, 13580764457377834041, 12635549236735416450, 17930064579773119626, 14879486686694324607, 9212708781170196788, 357347690345658614, 15436428048766097389, 5089204714765300123, 11165399311873161545, 12042794039346605265, 15927676903549361476, 9120348263769454156, 10517599934976061598, 6987137087681155918, 11181311136166944889, 187803040686893225 ) group by sn.END_INTERVAL_TIME order by sn.END_INTERVAL_TIME;
Only time will tell if this really is a helpful way to check system performance as the load grows, but I thought it was worth sharing what I had done. Some part of this might be helpful to others.
Bobby