查找运行时间超过 5 秒的查询

发布于 2024-10-03 02:05:08 字数 754 浏览 5 评论 0原文

我的朋友要求我在他的 Oracle 数据库上查找长时间运行的查询(超过 5 秒)。他想在定期间隔后进行某种轮询,并想向自己发送警报,以便他知道哪个查询需要很长时间才能执行并向他发送查询和相应的会话。

我写了这个 Oracle 查询:

    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

建议???

I was asked by my friend to find long running queries (more than 5 second) on his oracle database. He wanted to do some sort of polling after a periodic interval and wanted to send himself an alert so that he knows which query are taking so long to execute and send query and corresponding session to him.

I wrote this Oracle query :

    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

But he says that when he runs a query manually and calculates the time, the time it spends in executing it is a fraction of the result he is getting from the table generated by this particular query.

I wonder if my query is wrong , I have done some search but it still seems the query is fine.

Database is Oracle 10g

Suggestions???

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅紫色的梦幻 2024-10-10 02:05:08

ELAPSED_TIME 是SQL 语句所有运行时间的累计时间。因此对于频繁执行的查询来说它会很高。

将此视为一个快速查询(HINT 样式注释的目的是获取 V$SQLAREA 中的 SQL_ID):

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>

现在,您想要的是找到已运行的活动会话连续做某事超过五秒钟。因此,您需要会话级计时,特别是 V$SESSION 上的 LAST_CALL_ET,它是会话执行某项操作的秒数(如果其状态为 ACTIVE)或自上次操作以来的总运行时间(如果其状态为 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>

“它应该给我查询列表
目前正在执行或已经
最近执行完毕,我可以
查找查询花费的总时间
完成”

了语句执行的最近时间。但是,没有视图可以公开语句的每个单独执行的指标。如果您想要此类详细信息,则需要开始这是一个单独的问题。

ELAPSED_TIME is the accumulated time for all the times that SQL statement has been run. So it will be high for frequently executed queries.

Consider this a snappy query (the HINT-style comment is for the purposes of getting the SQL_ID in V$SQLAREA):

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

How long does it take to run? This long:

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> 

That's a relatively large chunk o' microsecs, because of the parse time. We can see that running it a couple more times doesn't add much to the elapsed time, and the average is much lower:

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>

And after running it another 100000 times ...

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>

Now, what you wantt is to find active sessions which have been doing something continuously for more than five seconds. So you need session-level timings, and in particular the LAST_CALL_ET on V$SESSION, which is the number of seconds the session has been doing something (if its status is ACTIVE) or the total elapsed time since its last action (if its status is INACTIVE).

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

So, consider this query. It's slow:

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

no rows selected

Elapsed: 00:00:07.56
SQL>

That's long enough to monitor using a query on V$SESSION. This one searches for statements which have been running for more than 3 seconds...

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>

and lo!

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>

"it should give me the list of queries
which are currently executing or have
recently finished executing and I can
find the total time the query took to
complete"

The LAST_ACTIVE_TIME on the V$SQLAREA view records the most recent time the statement was executed. However, there is no view which exposes the metrics for each individual execution of the statement. If you want that sort of detail you will need to start tracing. And that is a separate question.

完美的未来在梦里 2024-10-10 02:05:08

使用追踪:

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

Use the tracing:

# alter session set timed_statistics = true; 
# alter session set sql_trace = true; 
.....
# show parameter user_dump_dest 
$ tkprof <trc-файл> <txt-файл> 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文