Efter en nylig opgradering til 12.1.0.2 har jeg arbejdet på en række problemer med ydeevnen. Mange sådanne problemer er relateret til dårlig SQL, og en række problemer, jeg har løst, har bevist, var problemer i den gamle 11.2.0.4-udgivelse. Dette betyder bare, at det altid har været et problem. Men folk benytter lejligheden til opgraderingen til at få mig til at reparere ting, der har været i stykker i et stykke tid.
Mens jeg kiggede på ydeevneproblemer, er jeg stødt på to SQL-sætninger, der er ved at blive svin i vores system. Her er et skærmbillede af de to SQL-sætninger som set i Lighty:
Vi kan se, at den første SQL-sætning (SQL ID 4b4wp0a8dvkf0) bruger CPU og venter på læsninger fra kontrolfilen. Den anden SQL-sætning (SQL ID frjd8zfy2jfdq) bruger masser af CPU og har også en række andre ventehændelser. Her er SQL-teksten til disse udsagn.
SQL ID:frjd8zfy2jfdq
SELECT
executions
,end_of_fetch_count
,elapsed_time / px_servers elapsed_time
,cpu_time / px_servers cpu_time
,buffer_gets / executions buffer_gets
FROM
(
SELECT
SUM (executions) AS executions
,SUM (
CASE
WHEN px_servers_executions > 0
THEN px_servers_executions
ELSE executions
END
) AS px_servers
,SUM (end_of_fetch_count) AS end_of_fetch_count
,SUM (elapsed_time) AS elapsed_time
,SUM (cpu_time) AS cpu_time
,SUM (buffer_gets) AS buffer_gets
FROM
gv$sql
WHERE
executions > 0
AND sql_id = : 1
AND parsing_schema_name = : 2
SQL ID:4b4wp0a8dvkf0
SELECT
executions
,end_of_fetch_count
,elapsed_time / px_servers elapsed_time
,cpu_time / px_servers cpu_time
,buffer_gets / executions buffer_gets
FROM
(
SELECT
SUM (executions_delta) AS EXECUTIONS
,SUM (
CASE
WHEN px_servers_execs_delta > 0
THEN px_servers_execs_delta
ELSE executions_delta
END
) AS px_servers
,SUM (end_of_fetch_count_delta) AS end_of_fetch_count
,SUM (elapsed_time_delta) AS ELAPSED_TIME
,SUM (cpu_time_delta) AS CPU_TIME
,SUM (buffer_gets_delta) AS BUFFER_GETS
FROM
DBA_HIST_SQLSTAT s
,V$DATABASE d
,DBA_HIST_SNAPSHOT sn
WHERE
s.dbid = d.dbid
AND bitand (
nvl (
s.flag
,0
)
,1
) = 0
AND sn.end_interval_time > (
SELECT
systimestamp AT TIME ZONE dbtimezone
FROM
dual
) - 7
AND s.sql_id = : 1
AND s.snap_id = sn.snap_id
AND s.instance_number = sn.instance_number
AND s.dbid = sn.dbid
AND parsing_schema_name = : 2
)
)
Begge disse er en del af de nye Adaptive Query Optimization-funktioner nu i 12c. Mere specifikt relaterer disse til den automatiske dynamiske statistik-del af denne funktion. SQL ID frjd8zfy2jfdq er Oracle, der henter oplysninger om SQL-sætningsydelse fra GV$SQL. SQL ID 4b4wp0a8dvkf0 er Oracle, der henter de samme oplysninger om SQL-sætningsydelse fra Active Session History-tabellerne.
Bertand Drouvot diskuterer dette på sin blog her:https://bdrouvot.wordpress.com/2014/10/17/watch-out-for-optimizer_adaptive_features-as-it-may-have-a-huge-negative-impact/
Derudover sad jeg i en session af Christian Antognini på Oak Table World 2015, hvor han nævnte disse SQL-sætninger. Hans slides fra OTW er stort set de samme som disse:
http://www.soug.ch/fileadmin/user_upload/SIGs/SIG_150521_Tuning_R/Christian_Antognini_AdaptiveDynamicSampling_trivadis.pdf
Disse links ovenfor og de MOS-noter, jeg refererer til nedenfor, gav meget af grundlaget for den information, jeg præsenterer her.
Alle de Adaptive Query Optimization-funktioner formodes at gøre DBA's liv bedre. De formodes at hjælpe Optimizer med at træffe bedre beslutninger, selv efter at en SQL-sætning er begyndt at udføre. I dette specifikke tilfælde formodes disse forespørgsler at hjælpe CBO'en med at opnå bedre statistik, selvom statistikkerne mangler. Dette kan hjælpe med at forbedre SQL-ydeevnen, men som jeg fandt i mit tilfælde, hæmmer det den overordnede systemydeevne.
For mere om adaptiv forespørgselsoptimering, se note 2031605.1. Dette vil føre dig til andre noter, men især til denne diskussion, Note 2002108.1 Automatic Dynamic Statistics.
Det, der gør tingene værre, er, at mit produktionssystem, der ser denne adfærd, er Oracle RAC. Når SQL ID frjd8zfy2jfdq udføres på Oracle RAC-systemer, bruges parallel forespørgsel, hvilket er tydeligt fra mit skærmbillede af enq:PS – påstand og "PX%" ventehændelser.
Vi kan slå dynamisk sampling på som følger:
ændre systemsæt optimizer_dynamic_sampling=0 scope=both;
Standardværdien for denne parameter er 2.
For mig bruger disse forespørgsler ressourcer og påvirker den overordnede databaseydeevne. Alligevel er disse funktioner designet til at forbedre ydeevne. Der er altid en risiko for, at hvis jeg slår funktionen fra for at hjælpe med ydeevnen på et område, så vil det skade ydeevnen på et andet område. Men siden optimizer_dynamic_sampling<>11 for mig, bruger jeg ikke denne funktion fuldt ud, så jeg opnår ikke alle de fordele, jeg kunne være. Desuden er vores kode ikke afhængig af dynamisk sampling. Så det er sikkert for mig at slå dette fra.
Efter at have ændret parameteren, kunne jeg se en øjeblikkelig ændring som vist nedenfor.
Den røde linje angiver det tidspunkt, hvor jeg foretog ændringen. Det er tydeligt, at ASH-versionen af denne forespørgsel ikke længere udføres. V$SQL-versionen kører stadig, men ser ikke længere parallelle forespørgselsventehændelser. Det bruger for det meste kun CPU nu. Jeg betragter dette fremskridt, men ikke som en fuldstændig opløsning.
Som en sidebemærkning kunne jeg have slået alle Adaptive Query Optimization-funktioner fra med følgende:
alter system set optimizer_adaptive_features=false scope=both;
Men jeg ved, at jeg har forespørgsler, der "nyder" Adaptive Join Optimization, og jeg vil ikke slå det hele fra, kun dynamisk sampling.
Så hvad skal man nu gøre med SQL ID frjd8zfy2jfdq? Lad os se, om vi kan løse det resterende problem. Fra en af de MOS-noter, jeg linkede ovenfor, ved jeg, at vi kan indstille denne skjulte parameter:
alter system set "_optimizer_dsdir_usage_control"=0 scope=both;
Standardværdien for denne skjulte parameter var 126 i mit 12.1.0.2-system. Jeg fandt standardindstillingen med følgende:
select a.ksppinm name, b.ksppstvl value, b.ksppstdf deflt,
from
sys.x$ksppi a,
sys.x$ksppcv b
where a.indx = b.indx
and a.ksppinm like '\_%' escape '\'
and a.ksppinm like '%dsdir%'
order by name;
Denne værdi er vigtig, hvis jeg vil indstille den tilbage uden at skulle tage parameteren ud af SPFILE, hvilket ville kræve nedetid.
Jeg kan nu fortsætte med at ændre denne skjulte parameter og sætte den til nul. Sådan ser SQL-sætningen ud i Lighty efter ændringen:
Det ser ud til at være "mission accomplished" med at stoppe disse to SQL-sætninger i at blive eksekveret.
Dem, der kører 12.1.0.2 på Oracle RAC, vil måske gerne bekræfte, at disse to SQL-sætninger ikke forårsager deres egne ydeevneproblemer.
Dette ser ud til at være et af de tilfælde, hvor en funktion, der skal hjælpe med ydeevnen, faktisk gør det modsatte.