V roce 2015 jsem upgradoval naše databáze Oracle 11.2.0.4 na 12.1.0.2 a zaznamenal jsem určité problémy s výkonem související s naším používáním GTT. Blogoval jsem o těchto problémech zde.
Jádrem problému, který jsem se snažil vyřešit, bylo to, že změna chování v 12c vedla ke statistikám ukládání Oracle, že GTT má nula řádků, když tomu tak není. Statistiky ukazující počet řádků rovný nule vedou k úplnému prohledání tabulky a kartézským produktům na dotazy, které zahrnují GTT. Jak jsem uvedl v tomto blogovém příspěvku, použili jsme DBMS_STATS.SET_TABLE_STATS poté, co jsme tabulku naplnili daty, aby každá relace měla správné statistiky, abychom dosáhli lepšího plánu provádění.
Poté, co jsme upgradovali na Oracle 19c, jsme začali vidět další problémy s výkonem související s GTT. Dotazy, které používaly GTT, začaly čekat na událost čekání „cursor pin:S wait on X“. Mohla to být změna chování s novou verzí Oracle, ale také to mohlo být, že naši vývojáři používali GTT v našem kódu častěji a neměli s novou verzí nic společného.
U dotazů zapojených do události čekání na kurzorový pin jsem zaznamenal vysoký počet verzí příkazu SQL ve sdíleném fondu. Když jsem se dotázal V$SQL_SHARED_CURSOR, zjistil jsem, že PURGED_CURSOR=‘Y‘ pro tyto příkazy SQL. Kurzor se stává neplatným.
Při zkoumání tohoto problému jsem zjistil, že pokaždé, když jsme zavolali DBMS_STATS.SET_TABLE_STATS, abychom získali statistiky založené na relaci o GTT, zruší to platnost všech příkazů SQL, které používají tento GTT. Proto to čekání. Čekání nebylo dlouhé, takže mnoho koncových uživatelů si problému ani nevšimlo.
Ale pak jsme měli nový problém. Když zavoláte SET_TABLE_STATS, Oracle zapíše záznam do SYS.WRI$_OPTSTAT_TAB_HISTORY a můžete vidět hodnoty, které relace nastavila pro statistiky tabulky. Ve výchozím nastavení tato tabulka ukládá 30denní historii. Stůl se velmi rozrůstal a spotřebovával většinu SYSAUX. Vždy (hodinu?) Oracle odstraní záznamy starší než 30 dní. Toto pravidelné ořezávání této tabulky mělo nyní negativní dopad na výkon koncového uživatele. Níže je uveden graf výkonu od společnosti Lighty, který ukazuje dopad ořezávání této tabulky:
Celá ta děsivá červená barva je, když byly staré řádky odstraňovány z SYS.WRI$_OPTSTAT_TAB_HISTORY.
Takže moje „oprava“ výkonu před pěti lety přinesla další problém s výkonem. Pro zlepšení výkonu jsem vytvořil sdílené statistiky na GTT a přestal používat statistiky relace. Zde jsou kroky:
--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';
Jakmile budou sdílené statistiky na místě, odstraníme volání DBMS_SET_TABLE_STATS z našeho kódu.