视图V$SQL、V$SQLAREA 和 V$SQLSTATS 的区别

Oracle 数据库提供了三个动态视图,用于查询当前共享池中的所有 SQL 语句的执行统计信息。它们分别是 V S Q L 、 V SQL、V SQLVSQLAREA 和 V$SQLSTATS。本文将探讨它们之间的区别。

V$SQL 对于每个不同版本的 SQL 语句都有一行记录。这意味着每个子语句都有自己的执行统计信息,而且一个 SQL 语句在该视图中可能有多行记录。

V S Q L A R E A 和 V SQLAREA 和 V SQLAREAVSQLSTATS 对于每个不同的 SQL 字符串(即每个父游标)只有一行记录。这意味着所有子游标的统计信息,即该游标的不同版本,都被合并到一起。

以下示例说明了它们之间的区别。

首先,我们执行相同的 SQL 语句两次,同时在两次执行之间更改会话变量,以创建同一个SQL的两个执行版本:

SQL> select /* sql_version */ last_name from employees where EMPLOYEE_ID<10;
未选择行

SQL> alter session set optimizer_index_cost_adj=101;
会话已更改。

SQL> select /* sql_version */ last_name from employees where EMPLOYEE_ID<10;
未选择行

然后,我们查询 V S Q L 、 V SQL、V SQLVSQLAREA 和 V$SQLSTATS 中的 SQL 执行统计信息。

SQL> select sql_id, substr(sql_text,1,50), buffer_gets, ELAPSED_TIME, child_number, CHILD_ADDRESS from v$sql where sql_id='8qxn9jfkd7348';
SQL_ID          SUBSTR(SQL_TEXT,1,50)                                  BUFFER_GETS   ELAPSED_TIME   CHILD_NUMBER CHILD_ADDRESS
8qxn9jfkd7348   select /* sql_version */ last_name from employees                1           2571              0 0000000095FBF368
8qxn9jfkd7348   select /* sql_version */ last_name from employees                1           2679              1 0000000096560ED8

SQL> select sql_id, substr(sql_text,1,50), buffer_gets, ELAPSED_TIME from v$sqlarea where sql_id='8qxn9jfkd7348';
SQL_ID          SUBSTR(SQL_TEXT,1,50)                                  BUFFER_GETS   ELAPSED_TIME
8qxn9jfkd7348   select /* sql_version */ last_name from employees                2           5250

SQL> select sql_id, substr(sql_text,1,50), buffer_gets, ELAPSED_TIME from v$sqlstats where sql_id='8qxn9jfkd7348';
SQL_ID          SUBSTR(SQL_TEXT,1,50)                                  BUFFER_GETS   ELAPSED_TIME
8qxn9jfkd7348   select /* sql_version */ last_name from employees                2           5250

在这里,我们可以看到 V S Q L 包含两行 S Q L 语句的记录,而 V SQL 包含两行 SQL 语句的记录,而 V SQL包含两行SQL语句的记录,而VSQLAREA 和 V$SQLSTATS 只包含其中一行,并且执行统计信息列如 BUFFER_GETS 和 ELAPSED_TIME 已被汇总。

关于号主,姚远:

  • Oracle ACE(Oracle和MySQL数据库方向)
  • 华为云最有价值专家
  • 《MySQL 8.0运维与优化》的作者
  • 拥有 Oracle 10g、12c和19c OCM等数十项数据库认证
  • 曾任IBM公司数据库部门经理
  • 20+年DBA经验,服务2万+客户
  • 精通C和Java,发明两项计算机专利

在Oracle 10g R2 推出 V S Q L S T A T S 之前, V SQLSTATS 之前,V SQLSTATS之前,VSQLAREA 是我最喜欢的 SQL 调优视图之一。V S Q L S T A T S 与 V SQLSTATS 与 V SQLSTATSVSQLAREA 有几点不同:

  • V S Q L S T A T S 包含 S Q L 语句的完整文本,不再需要访问 V SQLSTATS 包含 SQL 语句的完整文本,不再需要访问 V SQLSTATS包含SQL语句的完整文本,不再需要访问VSQLAREA 和 V$SQLTEXT 来获取所需的信息。
  • Oracle声称V S Q L S T A T S 更快且更具扩展性。 [ V SQLSTATS 更快且更具扩展性。[V SQLSTATS更快且更具扩展性。[VSQLSTATS (oracle.com)](https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/V-SQLSTATS.html)
  • V$SQLSTATS 提供了更长的访问窗口,也就是说即使某些过期的SQL已经不在共享池中,仍然可能在这个视图中查询到。

在下一篇文章中,我将为读者提供一些现成的脚本用于查询V$SQLSTATS 找到需要优化的TOP SQL 。

### 如何在 Oracle 数据库中查看当前正在运行的 SQL 语句及其执行时间 为了查询当前正在运行的 SQL 语句以及它们的执行时间,可以利用 `v$session` `v$sqlarea` 系统视图来构建合适的 SQL 查询。以下是详细的实现方法: #### 使用 `v$session` `v$sqlarea` 通过连接 `v$session` `v$sqlarea` 视图,可以获得会话的相关信息以及对应的 SQL 文本性能数据。 ```sql SELECT s.sid, s.serial#, s.username, s.status, s.sql_id, s.prev_sql_id, q.sql_text, s.seconds_in_wait AS execution_time_seconds FROM v$session s LEFT JOIN v$sqlarea q ON s.sql_id = q.sql_id WHERE s.status = 'ACTIVE' AND s.sql_id IS NOT NULL; ``` 上述查询解释如下: - **s.sid**: 表示会话 ID。 - **s.serial#**: 表示会话序列号。 - **s.username**: 显示触发该 SQL 的用户名。 - **s.status**: 当前会话状态(通常关注 `'ACTIVE'` 状态)。 - **s.sql_id**: 正在执行的 SQL 的唯一标识符[^1]。 - **q.sql_text**: 对应 SQL 的文本内容。 - **execution_time_seconds**: 记录了会话等待的时间(单位为秒),可近似表示 SQL 执行时间[^2]。 需要注意的是,如果 SQL 被截断到 1000 字符,则可以通过 `v$sqltext` 获取完整的 SQL 语句[^3]。 #### 如果需要更精确的执行时间 对于更精确的执行时间统计,还可以结合 `v$session_event` 或者 `v$sqlstats` 来计算具体的耗时情况。例如: ```sql SELECT s.sid, s.serial#, s.username, s.sql_id, sq.elapsed_time / 1000000 AS elapsed_time_seconds -- 将微秒转换为秒 FROM v$session s JOIN v$sqlstats sq ON s.sql_id = sq.sql_id WHERE s.status = 'ACTIVE'; ``` 这里的关键字段是 `sq.elapsed_time`,它代表自 SQL 开始执行以来所消耗的实际时间(以微秒计)。将其除以 1,000,000 即得到以秒为单位的结果。 #### 处理超长 SQL 语句的情况 当遇到超过 1000 字符长度的 SQL 语句时,需借助 `v$sqltext_with_newlines` 或 `v$sqltext` 来拼接完整的 SQL 内容。以下是一个例子: ```sql SELECT piece, sql_text FROM v$sqltext WHERE sql_id = '&input_sql_id' ORDER BY piece ASC; ``` 这里的 `piece` 列指定了每一块 SQL 片段的位置次序,按升序排列即可还原原始 SQL。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姚远Oracle ACE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值