sql >> Databasteknik >  >> RDS >> Oracle

GTT-tabellstatistik och SYS.WRI$_OPTSTAT_TAB_HISTORY

Redan 2015 uppgraderade jag våra Oracle 11.2.0.4-databaser till 12.1.0.2 och upplevde några prestandaproblem relaterade till vår användning av GTT:er. Jag bloggade om dessa frågor här.

Kärnan i problemet jag försökte lösa var att en beteendeförändring i 12c ledde till Oracle-sparstatistik att GTT har noll rader när den inte gör det. Statistik som visar antalet rader är lika med noll leder till genomsökningar av hela tabeller och kartesiska produkter på frågor som involverar GTT. Som jag sa i det blogginlägget använde vi DBMS_STATS.SET_TABLE_STATS efter att vi fyllt i tabellen med data så att varje session skulle ha korrekt statistik för att komma fram till en bättre utförandeplan.

Efter att vi uppgraderat till Oracle 19c började vi se andra prestandaproblem relaterade till GTT. Frågor som använde GTT började vänta på "cursor pin:S wait on X" väntahändelsen. Detta kunde ha varit en beteendeförändring med den nya Oracle-versionen, men det kunde också ha varit våra utvecklare som använder GTT oftare i vår kod och inte har något att göra med den nya versionen.

För frågorna som är involverade i Cursor Pin wait-händelsen märkte jag ett stort antal versioner av SQL-satsen i den delade poolen. När jag frågade V$SQL_SHARED_CURSOR upptäckte jag att PURGED_CURSOR='Y' för dessa SQL-satser. Markören håller på att bli ogiltig.

När jag undersökte det här problemet upptäckte jag att det som händer är att varje gång vi ringde DBMS_STATS.SET_TABLE_STATS för att få sessionsbaserad statistik på GTT, ogiltigförklaras alla SQL-satser som använder den GTT. Därav väntan. Väntan var inte lång så många slutanvändare märkte inte ens problemet.

Men sedan hade vi ett nytt problem. När du ringer till SET_TABLE_STATS, skriver Oracle en post i SYS.WRI$_OPTSTAT_TAB_HISTORY och du kan se värdena som sessionen ställt in för tabellens statistik. Som standard lagrar den här tabellen 30 dagars historik. Bordet växte väldigt mycket och förbrukade det mesta av SYSAUX. Då och då (varje timme?) tar Oracle bort poster som är mer än 30 dagar gamla. Denna regelbundna beskärning av denna tabell påverkade nu slutanvändarens prestanda negativt. Följande är en prestandagraf från Lighty som visar effekten av beskärningen av denna tabell:

All den där skrämmande röda färgen är när de gamla raderna togs bort från SYS.WRI$_OPTSTAT_TAB_HISTORY.

Så min prestanda "fix" för fem år sedan introducerade ett annat prestandaproblem. För att förbättra prestanda var det jag gjorde att skapa delad statistik på GTT och sluta använda sessionsstatistik. Här är stegen:

--set prefs to SHARED globally      
exec DBMS_STATS.set_global_prefs ( pname => 'GLOBAL_TEMP_TABLE_STATS', pvalue => 'SHARED');
--set the table and index stats
exec dbms_stats.set_table_stats(ownname=>'MY_SCHEMA',tabname=>'MY_GTT_TABLE',numrows=>1000,numblks=>2,avgrlen=>15);
exec dbms_stats.set_index_stats(ownname=>'MY_SCHEMA',indname=>'GTT_INDEX',indlevel=>1,numlblks=>2,numdist=>15,clstfct=>28,numrows=>1000);
-- set prefs back to SESSION
exec DBMS_STATS.set_global_prefs ( pname => 'GLOBAL_TEMP_TABLE_STATS', pvalue => 'SESSION');
-- verify stats set
select num_rows,blocks,last_analyzed,scope
from dba_tab_statistics
where table_name ='MY_GTT_TABLE';
select blevel,leaf_blocks,distinct_keys,num_rows,clustering_factor,last_analyzed,scope
from dba_ind_statistics
where index_name='GTT_INDEX' and owner='MY_SCHEMA';

När den delade statistiken var på plats tar vi bort anropen till DBMS_SET_TABLE_STATS från vår kod.


  1. xampp MySQL startar inte

  2. Hur SQLite Count() fungerar

  3. Hur man konverterar DateTime till VarChar

  4. My 11g Optimizer Stats Job Quit on Me – Fixed