游标有什么问题?

Cha*_*kra 13 sql-server oracle cursor data-structures

SQL Server开发人员认为游标是一种不好的做法,除非在某些情况下.他们认为游标不是最佳使用SQL引擎,因为它是一个程序构造,并且违背了基于Set的RDBMS概念.

但是,Oracle开发人员似乎并不建议反对游标.Oracle的DML语句本身就是隐式游标.

为什么这种差异的方法?是因为这两种产品的制造方式,还是这种建议适用于这两种产品?

Qua*_*noi 22

游标有什么问题,它们经常被滥用,无论是在内部Oracle还是内部MS SQL.

游标用于保持稳定的结果集,您可以逐行检索.它们在运行查询时隐式创建,在完成后关闭.

当然,保持这样的结果需要一些资源:locks,latches,memory,甚至disk space.

释放这些资源的速度越快越好.

保持光标打开就像保持冰箱门打开一样

没有必要,你几个小时都不会这样做,但这并不意味着你永远不应该打开你的冰箱.

这意味着:

  • 你没有得到你的结果行到行和总结他们:你拨打SQLSUM来代替.
  • 您不执行整个查询并从游标获取第一个结果:您rownum <= 10向查询添加条件

至于Oracle处理过程中的游标需要臭名昭着SQL/PLSQL context switch,每次SQL从游标中获得查询结果时都会发生臭名昭着.

它涉及在线程之间传递大量数据并同步线程.

这是最刺激的事情之一Oracle.

这种行为的一个不太明显的后果是,如果可能的话,应该避免Oracle中的触发器.

创建触发器并调用DML函数等于打开光标选择更新的行并调用此游标的每一行的触发器代码.

仅存在触发器(即使是空触发器)可能会减慢DML操作10 times或更多操作.

一个测试脚本10g:

SQL> CREATE TABLE trigger_test (id INT NOT NULL)
  2  /

Table created

Executed in 0,031 seconds
SQL> INSERT
  2  INTO   trigger_test
  3  SELECT level
  4  FROM   dual
  5  CONNECT BY
  6     level <= 1000000
  7  /

1000000 rows inserted

Executed in 1,469 seconds
SQL> COMMIT
  2  /

Commit complete

Executed in 0 seconds
SQL> TRUNCATE TABLE trigger_test
  2  /

Table truncated

Executed in 3 seconds
SQL> CREATE TRIGGER trg_test_ai
  2  AFTER INSERT
  3  ON trigger_test
  4  FOR EACH ROW
  5  BEGIN
  6     NULL;
  7  END;
  8  /

Trigger created

Executed in 0,094 seconds
SQL> INSERT
  2  INTO   trigger_test
  3  SELECT level
  4  FROM   dual
  5  CONNECT BY
  6     level <= 1000000
  7  /

1000000 rows inserted

Executed in 17,578 seconds
Run Code Online (Sandbox Code Playgroud)

1.47没有触发器的17.57秒数,空触发器无效的秒数.


Gar*_*Ray 14

来自MSDN:游标实现

使用游标的效率低于使用默认结果集.在默认结果集中,从客户端发送到服务器的唯一数据包是包含要执行的语句的数据包.使用服务器游标时,必须将每个FETCH语句从客户端发送到服务器,在该服务器中必须将其解析并编译为执行计划.

如果Transact-SQL语句将返回一个相对较小的结果集,该结果集可以缓存在客户端应用程序可用的内存中,并且您在执行必须检索整个结果集的语句之前知道,请使用默认结果集.仅当需要游标操作来支持应用程序的功能时,或者只有部分结果集可能被检索时,才使用服务器游标.

我不是Oracle DBA,所以我无法真正谈论实现的不同之处.但是,从编程的角度来看,基于集合的操作几乎总是比处理游标中的结果更快.