在oracle中,显式游标是否将整个查询结果加载到内存中?

发布于 2024-08-24 10:12:59 字数 480 浏览 10 评论 0原文

我有一个大约有 10 亿行的表。我是唯一的用户,所以不存在锁等争用。 我注意到,当我运行这样的东西时:在

DECLARE   
  CURSOR cur IS SELECT col FROM table where rownum < N; 
BEGIN
  OPEN cur;
  LOOP
    dbms_output.put_line("blah")
  END LOOP;
  CLOSE cur;
END;

我按下回车键的时间和输出开始流入的时间之间有一个滞后。如果 N 很小,那么它是微不足道的。对于较大的 N(或没有 WHERE 子句),此延迟约为小时。

如您所知,我对 Oracle 很陌生,我假设游标只是在表中保留一个指针,它们在循环的每次迭代中都会更新该指针。所以我没想到滞后与执行迭代的表的大小成比例。这是错误的吗?游标是否会在迭代查询结果之前加载整个查询结果?

有没有一种方法可以在没有初始开销的情况下逐行迭代表?

I have a table with about 1 billion rows. I'm the sole user so there's no contention on locks, etc.
I noticed that when I run something like this:

DECLARE   
  CURSOR cur IS SELECT col FROM table where rownum < N; 
BEGIN
  OPEN cur;
  LOOP
    dbms_output.put_line("blah")
  END LOOP;
  CLOSE cur;
END;

there is a lag between the time when I hit enter and the time the output begins to flow in. If N is small then it's insignificant. For large N (or no WHERE clause) this lag is on the order of hours.

I'm new to oracle as you can tell, and I assumed that cursors just keep a pointer in the table which they update on every iteration of the loop. So I didn't expect a lag proportional to the size of the table over which iteration is performed. Is this wrong? Do cursors load the entire query result prior to iterating over it?

Is there a way to iterate over a table row by row without an initial overhead?

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

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

发布评论

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

评论(2

您所看到的是,直到程序完成后才显示 DBMS_OUTPUT.PUT_LINE 的输出。它没有告诉您有关查询返回第一行的速度的任何信息。 (我假设您打算在示例中实际获取数据)。

监视会话的方法有很多种,其中一种是这样的:

DECLARE   
  CURSOR cur IS SELECT col FROM table; 
  l_col table.col%ROWTYPE;
BEGIN
  OPEN cur;
  LOOP
    FETCH cur INTO l_col;
    EXIT WHEN cur%NOTFOUND;
    dbms_application_info.set_module('TEST',l_col);
  END LOOP;
  CLOSE cur;
END;

当该会话正在运行时,从另一个会话运行:

select action from v$session where module='TEST';

您将看到 ACTION 的值随着游标获取行而不断变化。

What you are seeing is that the output from DBMS_OUTPUT.PUT_LINE is not displayed until the program has finished. It doesn't tell you anything about how fast the query returned a first row. (I assume you intended to actually fetch data in your example).

There are many ways you can monitor a session, one is like this:

DECLARE   
  CURSOR cur IS SELECT col FROM table; 
  l_col table.col%ROWTYPE;
BEGIN
  OPEN cur;
  LOOP
    FETCH cur INTO l_col;
    EXIT WHEN cur%NOTFOUND;
    dbms_application_info.set_module('TEST',l_col);
  END LOOP;
  CLOSE cur;
END;

While that is running, from another session run:

select action from v$session where module='TEST';

You will see that the value of ACTION keeps changing as the cursor fetches rows.

メ斷腸人バ 2024-08-31 10:12:59

我还喜欢监视 v$session_longops 是否有 Oracle 优化器认为是“长操作”的操作:

select message, time_remaining
来自 v$session_longops
其中 time_remaining > 0;

I also like to monitor v$session_longops for operations deemed by the Oracle optimizer to be "long operations":

select message, time_remaining
from v$session_longops
where time_remaining > 0;

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文