游标有什么问题?

时间:2009-04-13 06:27:21

标签: sql-server oracle data-structures cursor

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

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

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

6 个答案:

答案 0 :(得分:22)

游标有什么问题,它们经常在OracleMS SQL中被滥用。

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

当然,保留这样的结果集需要一些资源:lockslatchesmemory,甚至disk space

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

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

你没有必要这么做几个小时,但这并不意味着你不应该打开你的冰箱。

这意味着:

  • 您没有逐行获得结果并将它们相加:您改为调用SQL的{​​{1}}。
  • 您不执行整个查询并从光标获取第一个结果:您在查询中附加SUM条件

等。

对于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 秒没有触发器,1.47秒,空触发器无效。

答案 1 :(得分:14)

来自MSDN:Cursor Implementations

  

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

     

如果是Transact-SQL语句   返回一个相对较小的结果集   可以缓存在内存中   可用于客户端应用程序,   你知道在执行之前   声明你必须检索   整个结果集,使用默认值   结果集。仅使用服务器游标   当需要游标操作时   支持的功能   申请,或只是部分   结果集可能会被检索。

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

答案 2 :(得分:3)

我一直被告知游标哪里有恶,但总是由MS SQL Server大师,因为它的性能不佳。关于Oracle的PL / SQL I found this saying when to use cursors

  

不使用游标会导致重复解析。如果未使用绑定变量,则会对所有SQL语句进行硬解析。这对性能有一个数量级的影响,并且完全不可扩展。使用带有绑定变量的游标,打开游标并多次执行。怀疑生成动态SQL的应用程序。

作为cursors are implicitly created on every operation,在需要时使用它们似乎没那么严厉:)

请记住,Oracle的实现更接近Postgres而不是Sybase(MS SQL Server的Genesis),因此每个不同任务的性能都会有所不同。如果可以的话,可以避免在可以交换的系统上调整性能的喧嚣后端,如果你需要同时使用两者,那么至少要达到共同点。 / tangential_topic

答案 3 :(得分:1)

我确信有人可以更详细地解释,但它基本上归结为SQL服务器中的游标是SLOW。

答案 4 :(得分:1)

答案 5 :(得分:0)

其他答案正确地指出了游标的性能问题,但他们没有提到SQL和关系数据库最适合基于集合的操作,而游标基本上是针对迭代操作。有一些操作(在更广泛的意义上)使用游标更容易执行,但在使用SQL时,您应该始终考虑使用数据集。游标经常被滥用,因为编码器没有掌握如何使用基于集合的操作来执行任务。