Co robi sesja w bazie danych Oracle?

Jeśli jesteś administratorem baz Oracle to czasem dostajesz pytanie 'dlaczego mój job/query/program wolno działa’. 

Jeśli tworzysz oprogramowanie dla baz danych Oracle to istnieje szansa, że takie pytanie nasuwa Ci się samo. A przynajmniej ja, jako admin Oracle, mam taką nadzieję.

W dalszej części artykułu powiem Ci skąd wziąć te informacje.

Wstęp 

Oracle jest motorem baz danych o bogatej instrumentacji. Dostęp do informacji o tym jak działa instancja bazy danych zapewniany jest poprzez dynamiczne widoki wydajnościowe V$_. 

Instalacje Real Application Clusters udostępniają informacje o wszystkich instancjach poprzez widoki globalne GV$_. 

Bardzo przydatnym, w strojeniu wydajności, jest V$ACTIVE_SESSION_HISTORY. Zawsze i łatwo dostępne na przykład przy pomocy komend SQL. Od Oracle 10g. Do zakupu z Diagnostic Pack. 

Czym jest V$ACTIVE_SESSION_HISTORY? 

Widok ten jest zbiorem faktów o historii działania ostatnich aktywnych sesji. Aktywnych oznacza mających cokolwiek innego niż 'Idle’ w kolumnie WAIT_CLASS widoku V$SESSION.

Ostatnich oznacza, że nie wiadomo ile historii zmieści się w pamięci, której reprezentacją jest widok. Trzeba pamiętać, że obszar pamięci przeznaczony dla danych ma określoną pojemność i zapisywany jest na zasadzie round robin. Po polsku karuzelowo. Czyli na ruchliwej bazie danych informacje będą z krótszego okresu czasu niż na bazie z małym ruchem. Najstarsze dane szybciej zostaną nadpisane najnowszymi.

Próbki wydajnościowe zbierane są co sekundę. Agregując dane, wg odpowiednich kolumn, dostajesz informacje na co poświęciła zasoby jak CPU, IO czy pamięć Twoja instancja bazy danych. Innymi słowy, która sesja, kiedy i wykonując jaką komendę konsumowała jakie zasoby instancji.

Każdy rekord ma określony numer próbki: SAMPLE_ID oraz jej czas: SAMPLE_TIME i dotyczy jednej konkretnej sesji: SESSION_ID i SESSION_SERIAL#.

Jakie informacje można znaleźć w V$ACTIVE_SESSION_HISTORY? 

Widok jest zbiorem faktów opisywanych przez wymiary. Dane można podzielić na kilka grup jak sesja, komenda SQL, wait, blok, obiekt czy aplikacja. Odpowiednie agregowanie surowych danych dostarczy informacji na wybrany temat.

Poniżej wycinek z wyniku komendy

desc V$ACTIVE_SESSION_HISTORY

z opisem znaczenia grup kolumn. 

Niepełna lista kolumn widoku V$ACTIVE_SESSION_HISTORY z podziałem na grupy.
Niepełna lista kolumn V$ACTIVE_SESSION_HISTORY z podziałem na grupy

Część kolumn usunąłem aby poprawić czytelność. 

Jak znaleźć sesję, która Cię interesuje? 

Gdy kontrolujesz proces – na przykład strojąc konkretne zapytanie czy procedurę składowaną – i wydajesz odpowiednie komendy ze swojego użytkownika i aplikacji typu SQLcl czy SQL Developer to znalezienie sesji nie nastręcza problemów. Wystarczy odpytać widok V$ACTIVE_SESSION_HISTORY wg kolumny PROGRAM i poszukać wartości 'SQLcl’ lub 'SQL Developer’. 

Zawartość kolumny PROGRAM dla popularnych klientów
Wynik z SQL Developera

Jeśli łączysz się sqlplus to w kolumnie PROGRAM znajdziesz 'sqlplus@<nazwa hosta na którym uruchamiasz sqlplus>’.

Jeśli to sesja aplikacji, na przykład pochodząca z serwera aplikacji łączącego się przez JDBC, to sprawa jest trudniejsza. Zazwyczaj jest wiele takich sesji należących do tego samego użytkownika, mających w kolumnie PROGRAM 'JDBC Thin Client’, a w MACHINE nazwę hosta na którym pracuje serwer aplikacji. 

Możesz ograniczać wynik do określonej komendy. Przyrównujesz SQL_OPNAME do DELETE/UPDATE/INSERT/SELECT/… 

Nawet takie podejście nie gwarantuje znalezienia poszukiwanej sesji. Może być wiele wykonujących tę samą komendę tylko innym SQL. 

Jak znaleźć zapytanie, które Cię interesuje? 

Jeśli nie możesz znaleźć sesji możesz odnaleźć interesujący SQL_ID komendy SQL. 

Kolejnym wartym uwagi dynamicznym widokiem wydajnościowym jest V$SQL. Dzięki niemu uzyskujesz dostęp do statystyk wykonania komend SQL przechowywanych przez instancję w pamięci podręcznej. Czyli do komend, które były już wykonane przez instancję.

Zamiast V$SQL masterzy Oracle zalecają używanie V$SQLSTATS. Dane mają większą retencję, a widok lepiej się skaluje. Jest szybszy.

W kolumnie SQL_TEXT znajdziesz pierwsze 1000 znaków komendy SQL. Jeśli poszukiwana przez Ciebie komenda zawiera jakiś charakterystyczny ciąg znaków możesz wyszukać go tutaj. Na przykład tak:

SELECT 
  sql_id 
FROM 
  v$sql 
WHERE 
  sql_text like '%charakterystyczny ciąg znaków%';

Aby łatwiej było znaleźć takie komendy możesz je odpowiednio modyfikować umieszczając własne znaczniki w komentarzach. Na przykład tak:

SELECT /* charakterystyczny napis Marcina */ 
  kolumna1 
  ,kolumna2 
FROM 
  bardzo_duża_tabela 
WHERE 
  kolumna_która_nie_ma_indeksu is null;

Widok V$SQL, w innych kolumnach, udostępnia wiele innych wartościowych informacji, o komendach SQL. O tym w następnych artykułach. 

Mając SQL_ID zapytania, które Cię interesuje łatwo, w ASH, znajdziesz sesje, które je wykonywały. Przeszukujesz ASH wg kolumny SQL_ID. Pozostaje wybranie tej sesji, która interesuje Ciebie. Na przykład wg czasu rozpoczęcia wykonywania komendy SQL przez instancję udostępnionego w kolumnie SQL_EXEC_START. 

Jak prześledzić co robiła sesja? 

W poprzednich paragrafach pokazałem jak odnaleźć SESSION_ID i SESSION_SERIAL#, które jednoznacznie identyfikują sesję. Gdy masz te informacje to możesz agregować dane z ASH wg nich i dowiedzieć się na które SQL_ID, wykonywane w czasie trwania sesji, instancja poświęciła najwięcej czasu. Czyli, które SQL_ID trwało najdłużej. 

Możesz to zrobić w taki sposób: 

SELECT
  sql_exec_start
  ,sql_id 
  ,count(*) as "czas(s)"  
FROM  
  v$active_session_history  
WHERE  
  SESSION_ID=<SESSION_ID interesującej Cię sesji>
  and SESSION_SERIAL#=<SERIAL# interesującej Cię sesji>
GROUP BY  
  sql_exec_start, sql_id
ORDER BY  
  sql_exec_start;

W ten sposób wychwycisz wszystkie zapytania uruchamiane na przykład przez procedurę składowaną albo job. Będą posortowane wg czasu ich wykonania. Zawęzisz strojenie z całej procedury do konkretnego zapytania. 

Mając wartości SQL_ID możesz odnaleźć tekst komendy SQL razem z planem wykonania wywołując funkcję DISPLAY_CURSOR pakietu DBMS_XPLAN

SELECT 
  * 
FROM 
  table(dbms_xplan.display_cursor(sql_id=>'<SQL_ID interesującej Cię komendy SQL>', format=>'ALLSTATS LAST'));
Jak znaleźć zapytania, którym warto się przyjrzeć? 

Do strojenia zapytań można podejść bardziej proaktywnie. Czyli nie czekać na zgłoszenie od użytkowników tylko zerknąć na co instancja zużywa najwięcej zasobów. 

Zapytania, którym warto się przyjrzeć to takie, które konsumują najwięcej zasobów instancji. Mogą to robić sporadyczne lecz bardzo kosztowne zapytania lub nie tak znowu kosztowne, ale bardzo częste. Jedne i drugie będą pojawiać się często w widoku ASH. 

Kiepska wydajność znaczy, że użytkownik długo czeka na wykonanie komendy SQL. Czyli w wielu próbkach – wielu rekordach V$ACTIVE_SESSION_HISTORY – będzie występować ten sam SQL_ID. Wystarczy zagregować dane z ASH wg numeru SQL_ID. 

SELECT 
  sql_id 
  ,count(*) as "czas(s)" 
FROM 
  v$active_session_history 
WHERE 
  sql_id is not null 
GROUP BY 
  sql_id 
ORDER BY 
  count(*) desc;
Wynik zapytania do V$ACTIVE_SESSION_HISTORY
Wynik zapytania z SQL Developera

Jeśli interesuje Cię jedynie ostatnie kilka minut możesz ograniczyć ilość przeszukiwanych próbek wg kolumny SAMPLE_TIME. Na przykład do ostatnich 10 minut. 

SELECT 
  sql_id 
  ,count(*) as "czas(s)" 
FROM 
  v$active_session_history 
WHERE 
  sql_id is not null 
  and sample_time>sysdate - interval '10' minute 
GROUP BY 
  sql_id 
ORDER BY 
  count(*) desc;
Wynik zapytania do V$ACTIVE_SESSION_HISTORY ograniczonego czasowo
Wynik zapytania z SQL Developera

Zakres dat, dostępnych próbek, sprawdzisz zapytaniem: 

SELECT 
  min(sample_time) 
  ,max(sample_time) 
FROM 
  v$active_session_history;
Inne narzędzia do przeglądania danych ASH 

Dostęp do danych ASH zapewniają narzędzia dostarczane przez Oracle. Najprostszym tekstowym jest ASH Report. Dostępny jako skrypt sql: $ORACLE_HOME/rdbms/admin/ashrpt.sql zainstalowany razem z binariami motoru bazy danych. 

Wygeneruje dla Ciebie raport z działania instancji za zadany czas. Zapisze go w pliku tekstowym lub html w katalogu z którego uruchamiasz sqlplus. Może to być maszyna zdalna. Skrypt, w zależności od wybranych przez Ciebie opcji, wywołuje odpowiednią funkcję ASH_% z pakietu DBMS_WORKLOAD_REPOSITORY.

Skrypt możesz uruchomić z poziomu sqlplus komendą: @?/rdbms/admin/ashrpt. W sqlplus znak zapytania zastępuje ORACLE_HOME.

Uruchomienie ashrpt.sql z okna terminala
Wywołanie ashrpt.sql z terminala

Jeśli robisz to na maszynie zdalnej, gdzie jest zainstalowany tylko klient, to skrypt trzeba skopiować z binariów motoru bazy danych do ORACLE_HOME klienta. Inaczej musisz podać pełną ścieżkę do skryptu.

Więcej na temat generowania raportów ASH w dokumentacji Generating an ASH Report Using the Command-Line Interface.

Widok DBA z SQL Developera
Dostęp do ASH z SQL Developera

SQL Developer zapewni dostęp poprzez menu w okienku połączeń dla DBA. Okienko dostępne w menu 'View’.

Jest także niezależny od Oracle produkt ASH Viewer. Potrafi 'udawać’, że ASH jest dostępne. Trzeba pamiętać, że opisana przeze mnie funkcjonalność dostępna jest po opłaceniu licencji Diagnostic and Tuning Pack. Gdy nie masz tej licencji używasz połączenia standard. Gdy masz to enterprise. 

Strona ASH Viewer na sourceforge
Strona ASH Viewer na sourceforge

Last but not least jest Enterprise Manager. Daje graficzną reprezentację danych z ASH w czasie rzeczywistym. 

Skomentuj, który sposób dostępu do danych z ASH jest Tobie najbliższy. 

Podsumowanie

Przedstawiłem jeden z podstawowych sposobów wykorzystania danych z widoku V$ACTIVE_SESSION_HISTORY. Więcej informacji na ten temat znajdziesz w dokumentacji Database Performance Tuning Guide.

Oraz w Reference V$ACTIVE_SESSION_HISTORY.

Odpowiednio zagregowane dane ASH pokażą Ci największych konsumentów CPU, IO czy pamięci. O czym w kolejnych artykułach.

Prowadzę szkolenia i kursy z podstaw SQL. Sprawdź ofertę moich kursów SQL.

Marcin Badtke

Przyjaźnie o SQL, bazach danych i ludziach

Może Ci się spodobać...

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *