Найти запрос выполняется более 5 секунд - PullRequest
1 голос
/ 17 ноября 2010

Мой друг попросил меня найти в своей базе данных оракула длительные запросы (более 5 секунд).Он хотел сделать какой-то опрос после определенного промежутка времени и хотел отправить себе предупреждение, чтобы он знал, какой запрос занимает так много времени, чтобы выполнить и отправить ему запрос и соответствующий сеанс.

Я написал этот Oraclequery:

    select    sess.sid,
    sess.username,
    sess.paddr,
    sess.machine,
    optimizer_mode,
    sess.schemaname,
    hash_value,
    address,
    sess.sql_address,
    cpu_time,
    elapsed_time,
    sql_text
from    v$sql sql, v$session sess
where 
        sess.sql_hash_value = sql.hash_value
    and     sess.sql_address = sql.address
    and     sess.username is not null
    and     elapsed_time > 1000000  * 5
order by    
    cpu_time desc

Но он говорит, что когда он запускает запрос вручную и вычисляет время, время, которое он тратит на его выполнение, является частью результата, который он получает из таблицы, сгенерированной этим конкретным запросом..

Интересно, если мой запрос неправильный, я провел какой-то поиск, но все равно кажется, что запрос в порядке.

База данных Oracle 10g

Предложения ???

Ответы [ 2 ]

13 голосов
/ 17 ноября 2010

ELAPSED_TIME - это накопленное время за все время выполнения оператора SQL. Так что оно будет высоким для часто выполняемых запросов.

Считайте, что это быстрый запрос (комментарий в стиле HINT предназначен для получения SQL_ID в V $ SQLAREA):

select /*+ fast_running_query */ id
from big_table
where id = 1
/

Как долго длится бег? Это долго:

SQL> select elapsed_time
  2         , executions
  3         , elapsed_time / executions as avg_ela_time
  4  from v$sqlarea
  5  where sql_id = '73c1zqkpp23f0'
  6  /

ELAPSED_TIME EXECUTIONS AVG_ELA_TIME
------------ ---------- ------------
      235774          1       235774

SQL> 

Это относительно большой кусок микросек, из-за времени разбора. Мы видим, что запуск его еще пару раз не сильно увеличивает прошедшее время, а среднее значение намного ниже:

SQL> r
  1  select elapsed_time,
  2         executions,
  3         elapsed_time / executions as avg_ela_time
  4  from v$sqlarea
  5* where sql_id = '5v4nm7jtq3p2n'

ELAPSED_TIME EXECUTIONS AVG_ELA_TIME
------------ ---------- ------------
      237570          3        79190

SQL>

И после запуска еще 100000 раз ...

SQL> r
  1  select elapsed_time,
  2         executions,
  3         elapsed_time / executions as avg_ela_time
  4  from v$sqlarea
  5* where sql_id = '5v4nm7jtq3p2n'

ELAPSED_TIME EXECUTIONS AVG_ELA_TIME
------------ ---------- ------------
     1673900     100003   14.3809724

SQL>

Теперь вам нужно найти активные сеансы, которые выполняли что-то непрерывно более пяти секунд. Таким образом, вам нужны тайминги на уровне сеанса и, в частности, LAST_CALL_ET для V $ SESSION, который представляет собой количество секунд, в течение которых сеанс что-то делал (если он имеет статус ACTIVE), или общее время, прошедшее с момента его последнего действия (если его статус НЕАКТИВНО).

select sid
       , serial#
       , sql_address
       , last_call_et
from v$session
where status = 'ACTIVE'
and last_call_et > sysdate - (sysdate-(5/86400))
/

Итак, рассмотрим этот запрос. Это медленно:

SQL> select /*+ slow_running_query */ *
  2  from big_table
  3  where col2 like '%whatever%'
  4  /

no rows selected

Elapsed: 00:00:07.56
SQL>

Этого достаточно, чтобы отслеживать, используя запрос к V $ SESSION. Этот выполняет поиск операторов, которые выполнялись более 3 секунд ...

SQL> select sid
  2         , serial#
  3         , sql_id
  4         , last_call_et
  5  from v$session
  6  where status = 'ACTIVE'
  7  and last_call_et > sysdate - (sysdate - (3/86400))
  8  and username is not null
  9  /

       SID    SERIAL# SQL_ID        LAST_CALL_ET
---------- ---------- ------------- ------------
       137          7 096rr4hppg636            4
       170          5 ap3xdndsa05tg            7

SQL>

и вот!

SQL> select sql_text from v$sqlarea where sql_id = 'ap3xdndsa05tg'
  2  /

SQL_TEXT
--------------------------------------------------------------------------------
select /*+ slow_running_query */ * from big_table where col2 like '%whatever%'

SQL>

"это должно дать мне список запросов которые в настоящее время исполняются или имеют недавно закончил выполнение, и я могу найти общее время, затраченное на запрос полный "

LAST_ACTIVE_TIME в представлении V $ SQLAREA записывает самое последнее время выполнения оператора. Тем не менее, нет представления, которое предоставляет метрики для каждого отдельного выполнения оператора. Если вам нужны такие подробности, вам нужно начать трассировку. И это отдельный вопрос.

0 голосов
/ 17 ноября 2010

Использовать трассировку:

# alter session set timed_statistics = true; 
# alter session set sql_trace = true; 
.....
# show parameter user_dump_dest 
$ tkprof <trc-файл> <txt-файл> 
...