Использование ЦП Oracle превышает 100% - PullRequest
0 голосов
/ 06 ноября 2019

Мне нужно отслеживать использование процессора в Oracle 12c, и для этого я использую следующий фрагмент кода:

SELECT
            *
        FROM
            (
                SELECT
                    username,
                    sid,
                    round( (cpu_usage / (
                        SELECT
                            SUM(value) total_cpu_usage
                        FROM
                            v$sesstat t
                            INNER JOIN v$session s ON(t.sid = s.sid)
                            INNER JOIN v$statname n ON(t.statistic# = n.statistic#)
                        WHERE
                            n.name LIKE '%CPU used by this session%'
                            AND   nvl(s.sql_exec_start,s.prev_exec_start) >= SYSDATE - 1 / 24
                            AND   s.status = 'ACTIVE'
                    ) ) * 100,2) cpu_usage_per_cent,
                    module_info,
                    client_info,
                    machine
                FROM
                    (
                        SELECT
                            nvl(s.username,'Oracle Internal Proc.') username,
                            s.sid,
                            t.value cpu_usage,
                            nvl(s.module,s.program) module_info,
                            DECODE(s.osuser,'oracle',s.client_info,s.osuser) client_info,
                            s.machine
                        FROM
                            v$sesstat t
                            INNER JOIN v$session s ON ( t.sid = s.sid )
                            INNER JOIN v$statname n ON ( t.statistic# = n.statistic# )
                        WHERE
                            n.name LIKE '%CPU used by this session%'
                            AND   nvl(s.sql_exec_start,s.prev_exec_start) >= SYSDATE - 1 / 24
                            AND   s.status = 'ACTIVE'
                    ) s1
            )
        WHERE
            cpu_usage_per_cent > 0;

пока все хорошо, но время от времени SUM (CPU_USAGE_PER_CENT)превышает 100%. Более того, иногда оно превышает 100% для одного соединения.

Может кто-нибудь объяснить мне, почему так? Я ожидаю, что SUM (CPU_USAGE_PER_CENT) будет (редко) 100% и никогда не будет превышать 100% для одного соединения.

Большое спасибо.

1 Ответ

0 голосов
/ 06 ноября 2019

Кажется, что моя проблема возникла из-за операции ROUND:

round( (cpu_usage / (
                        SELECT
                            SUM(value) total_cpu_usage
                        FROM
                            v$sesstat t
                            INNER JOIN v$session s ON(t.sid = s.sid)
                            INNER JOIN v$statname n ON(t.statistic# = n.statistic#)
                        WHERE
                            n.name LIKE '%CPU used by this session%'
                            AND   nvl(s.sql_exec_start,s.prev_exec_start) >= SYSDATE - 1 / 24
                            AND   s.status = 'ACTIVE'
                    ) ) * 100,2) 

2 части операции деления между "cpu_usage" и "SUM (value)" генерируют 2 различных статистических значения.

Я заменил весь оператор SELECT на:

WITH main_select AS (
    SELECT
        nvl(s.username,'Oracle Internal Proc.') username,
        s.sid,
        t.value cpu_usage,
        nvl(s.module,s.program) module_info,
        DECODE(s.osuser,'oracle',s.client_info,s.osuser) client_info,
        s.machine
    FROM
        v$sesstat t
        INNER JOIN v$session s ON ( t.sid = s.sid )
        INNER JOIN v$statname n ON ( t.statistic# = n.statistic# )
    WHERE
        n.name LIKE '%CPU used by this session%'
        AND   nvl(s.sql_exec_start,s.prev_exec_start) >= SYSDATE - 1 / 24
        AND   s.status = 'ACTIVE'
),sum_select AS (
    SELECT
        SUM(cpu_usage) suma
    FROM
        main_select
) SELECT
    username,
    sid,
    round( (main_select.cpu_usage / suma) * 100,2) cpu_usage,
    module_info,
    client_info,
    machine
  FROM
    main_select,
    sum_select
  WHERE
    round( (main_select.cpu_usage / suma) * 100,2) > 0;

При этом представление статистики будет опрошено только один раз и будет иметь одинаковые значения во всех операциях.

...