Using Time Model to measure the database workload and performance

Neste artigo, vamos simular o processamento no banco de dados, aumentando gradativamente o seu workload, e ver o seu reflexo na Time Model. Criaremos uma tabela para salvar os snapshots sobre DB Time, DB CPU, e o total de waits, com objetivo de analisar os dados posteriormente para comparação. Obviamente, na vida real, isso não é necessário, pois temos um recurso que executa isso de forma muito mais completa e automática, que abordaremos em outros artigos (AWR).

Gerando script que criará a tabela que abrigará os dados históricos:

cat > create_tm_history.sql <<EOL 
 
-- create table to save DBTIME, DB CPU, and total waits in it 
DROP TABLE TM_HISTORY; 
DROP SEQUENCE S; 
CREATE SEQUENCE S; 
CREATE TABLE TM_HISTORY AS SELECT S.NEXTVAL AS SNAP_ID, 
    DBTIME.VALUE/1000000 DBTIME, 
    DBCPU.VALUE/1000000 DBCPU, 
    (DBTIME.VALUE-DBCPU.VALUE)/1000000 WAIT_TIME, 
    (SELECT COUNT(*) FROM V\$SESSION WHERE USERNAME IS NOT NULL) USERS_CNT 
FROM V\$SYS_TIME_MODEL DBTIME, V\$SYS_TIME_MODEL DBCPU 
WHERE DBTIME.STAT_NAME = 'DB time' AND DBCPU.STAT_NAME = 'DB CPU'; 
EOL

Execução:

[oracle@oel7 scripts]$ pwd
/oracle/scripts
[oracle@oel7 scripts]$ cat > create_tm_history.sql <<EOL
>
WHERE DBTIME.STAT_NAME = 'DB time' AND DBCPU.STAT_NAME = 'DB CPU';
EOL> -- create table to save DBTIME, DB CPU, and total waits in it
> DROP TABLE TM_HISTORY;
> DROP SEQUENCE S;
> CREATE SEQUENCE S;
> CREATE TABLE TM_HISTORY AS SELECT S.NEXTVAL AS SNAP_ID,
> DBTIME.VALUE/1000000 DBTIME,
> DBCPU.VALUE/1000000 DBCPU,
> (DBTIME.VALUE-DBCPU.VALUE)/1000000 WAIT_TIME,
> (SELECT COUNT(*) FROM V\$SESSION WHERE USERNAME IS NOT NULL) USERS_CNT
> FROM V\$SYS_TIME_MODEL DBTIME, V\$SYS_TIME_MODEL DBCPU
> WHERE DBTIME.STAT_NAME = 'DB time' AND DBCPU.STAT_NAME = 'DB CPU';
> EOL
[oracle@oel7 scripts]$

Script para retornar os dados da tabela criada:

cat > display_tm_history.sql << EOL 
 
-- retrieve data from TM_HISTORY 
 
set linesize 180 
SELECT 
    TO_CHAR(DBTIME,'999,999,999') DBTIME, 
    TO_CHAR(DBCPU,'999,999,999') DBCPU, 
    ROUND(DBCPU - LAG(DBCPU, 1, 0) OVER (ORDER BY DBCPU)) AS DBCPU_DIFF, 
    TO_CHAR(WAIT_TIME,'999,999,999,999') WAIT_TIME, 
    ROUND(WAIT_TIME - LAG(WAIT_TIME, 1, 0) OVER (ORDER BY WAIT_TIME)) AS WAIT_TIME_DIFF, 
    TO_CHAR((DBTIME-DBCPU)/DBTIME*100,'99.99') || '%' WAIT_PCT, USERS_CNT, 
    ROUND((DBTIME-DBCPU)/USERS_CNT) WAIT_USER_SHARE 
FROM TM_HISTORY 
ORDER BY SNAP_ID; 
EOL

Log:

[oracle@oel7 scripts]$ cat > display_tm_history.sql << EOL
>
> -- retrieve data from TM_HISTORY
>
> set linesize 180
> SELECT
> TO_CHAR(DBTIME,'999,999,999') DBTIME,
> TO_CHAR(DBCPU,'999,999,999') DBCPU,
> ROUND(DBCPU - LAG(DBCPU, 1, 0) OVER (ORDER BY DBCPU)) AS DBCPU_DIFF,
> TO_CHAR(WAIT_TIME,'999,999,999,999') WAIT_TIME,
> ROUND(WAIT_TIME - LAG(WAIT_TIME, 1, 0) OVER (ORDER BY WAIT_TIME)) AS WAIT_TIME_DIFF,
> TO_CHAR((DBTIME-DBCPU)/DBTIME*100,'99.99') || '%' WAIT_PCT, USERS_CNT,
> ROUND((DBTIME-DBCPU)/USERS_CNT) WAIT_USER_SHARE
> FROM TM_HISTORY
> ORDER BY SNAP_ID;
> EOL
[oracle@oel7 scripts]$

Script para gerar os snapshots:

cat > take_tm_snapshot.sql <<EOL 
 
-- save the current time model basic statistics into the TM_HISTORY table 
INSERT INTO TM_HISTORY 
SELECT 
    S.NEXTVAL AS SNAP_ID, 
    DBTIME.VALUE/1000000 DBTIME, 
    DBCPU.VALUE/1000000 DBCPU, 
    (DBTIME.VALUE-DBCPU.VALUE)/1000000 WAIT_TIME, 
    (SELECT COUNT(*) FROM V\$SESSION WHERE USERNAME IS NOT NULL) USERS_CNT 
FROM V\$SYS_TIME_MODEL DBTIME, V\$SYS_TIME_MODEL DBCPU 
WHERE DBTIME.STAT_NAME = 'DB time' AND DBCPU.STAT_NAME = 'DB CPU'; 
COMMIT; 
EOL

Log:

[oracle@oel7 scripts]$ cat > take_tm_snapshot.sql <<EOL
>
> -- save the current time model basic statistics into the TM_HISTORY table
> INSERT INTO TM_HISTORY
> SELECT
> S.NEXTVAL AS SNAP_ID,
> DBTIME.VALUE/1000000 DBTIME,
> DBCPU.VALUE/1000000 DBCPU,
> (DBTIME.VALUE-DBCPU.VALUE)/1000000 WAIT_TIME,
> (SELECT COUNT(*) FROM V\$SESSION WHERE USERNAME IS NOT NULL) USERS_CNT
> FROM V\$SYS_TIME_MODEL DBTIME, V\$SYS_TIME_MODEL DBCPU
> WHERE DBTIME.STAT_NAME = 'DB time' AND DBCPU.STAT_NAME = 'DB CPU';
> COMMIT;
> EOL
[oracle@oel7 scripts]$

Criando nossa estrutura:

SQL> @create_tm_history.sql
 
Table dropped.
 
 
Sequence dropped.
 
 
Sequence created.
 
 
Table created.

Visualizando os dados da tabela:

SQL> @display_tm_history.sql
 
DBTIME       DBCPU        DBCPU_DIFF WAIT_TIME        WAIT_TIME_DIFF WAIT_PC  USERS_CNT WAIT_USER_SHARE
------------ ------------ ---------- ---------------- -------------- ------- ---------- ---------------
          38            2          2               35             35  93.44%          3              12

Abrindo o SwingBench, e configurando uma carga simulando 10 usuários simultâneos:

Assim que vejo que os processos estão sendo realizados no banco, executo o script para tirar o snapshot:

[oracle@oel7 scripts]$ sqlplus / as sysdba
 
SQL*Plus: Release 19.0.0.0.0 - Production on Mon Sep 13 20:37:16 2021
Version 19.3.0.0.0
 
Copyright (c) 1982, 2019, Oracle.  All rights reserved.
 
 
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
 
SQL> @take_tm_snapshot.sql
 
1 row created.
 
 
Commit complete.

Parando o processamento:

Analisando o conteúdo de nossa tabela. O números de usuários aumentaram, e a porcetagem de Waits (que já eram altas, mas que podemos desconsiderar pois eu havia acabado de levantar o banco) também:

SQL> @display_tm_history.sql
 
DBTIME       DBCPU        DBCPU_DIFF WAIT_TIME        WAIT_TIME_DIFF WAIT_PC  USERS_CNT WAIT_USER_SHARE
------------ ------------ ---------- ---------------- -------------- ------- ---------- ---------------
          38            2          2               35             35  93.44%          3              12
         601           19         17              581            546  96.77%         13              45

Agora vou fazer a mesma dinâmica, mas aumentando o número de usuário para 30, e depois para 60, retirando um snapshot de cada momento:

SQL> @take_tm_snapshot.sql
 
1 row created.
 
 
Commit complete.
SQL> @take_tm_snapshot.sql
 
1 row created.
 
 
Commit complete.

Com o material, podemos analisar o ambiente, até em relação à sua escalabilidade. Em ambientes reais, o ideal é nos atentarmos na porcentagem de waits gerados, pois podem ser um indicativo de lentidão. Quanto maior o número de usuários clientes, maior será a CPU Time e DB Time. Porém, caso este número aumente, e a proporção de CPU e DB Time não é a mesma a mesma, temos um problema de escalabilidade, onde os DB Waits aumentam mais que o DB CPU.

SQL> @display_tm_history.sql
 
DBTIME       DBCPU        DBCPU_DIFF WAIT_TIME        WAIT_TIME_DIFF WAIT_PC  USERS_CNT WAIT_USER_SHARE
------------ ------------ ---------- ---------------- -------------- ------- ---------- ---------------
          38            2          2               35             35  93.44%          3              12
         601           19         17              581            546  96.77%         13              45
         991           68         49              923            342  93.13%         33              28
       1,517          219        151            1,299            375  85.58%         63              21

Obs: Este procedimento foi criado pelo senhor Ahmed Baraka (www.ahmedbaraka.com) e foi apenas reproduzido por mim em um laboratório pessoal para fins de aprendizado.

Leave a Comment

Your email address will not be published.