SQL Server 开发人员认为游标是一种不好的做法,除非在某些情况下。他们认为 Cursors 没有最佳地使用 SQL 引擎,因为它是一个过程构造并且破坏了基于集合的 RDBMS 概念。
但是,Oracle 开发人员似乎不建议反对 Cursors。Oracle 的 DML 语句本身就是隐式游标。
为什么在方法上有这种差异?是因为这两种产品的制造方式,还是这个建议适用于两种产品?
SQL Server 开发人员认为游标是一种不好的做法,除非在某些情况下。他们认为 Cursors 没有最佳地使用 SQL 引擎,因为它是一个过程构造并且破坏了基于集合的 RDBMS 概念。
但是,Oracle 开发人员似乎不建议反对 Cursors。Oracle 的 DML 语句本身就是隐式游标。
为什么在方法上有这种差异?是因为这两种产品的制造方式,还是这个建议适用于两种产品?
游标的问题在于它们经常被滥用,无论是 inOracle
还是 in MS SQL
。
光标用于保持稳定的结果集,您可以逐行检索。它们在您的查询运行时隐式创建,并在完成时关闭。
当然,保持这样的结果集需要一些资源:locks
, latches
, memory
, 甚至disk space
。
这些资源释放得越快越好。
保持光标打开就像保持冰箱门打开一样
您不会在没有必要的情况下连续数小时这样做,但这并不意味着您永远不应该打开冰箱。
这意味着:
SQL
's 。SUM
rownum <= 10
条件附加到查询, ETC。
至于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
没有触发器的17.57
秒数,空触发器的秒数什么都不做。
使用游标的效率低于使用默认结果集。在默认结果集中,从客户端发送到服务器的唯一数据包是包含要执行的语句的数据包。使用服务器游标时,每个 FETCH 语句都必须从客户端发送到服务器,在服务器上必须对其进行解析并编译成执行计划。
如果 Transact-SQL 语句将返回一个相对较小的结果集,该结果集可以缓存在客户端应用程序可用的内存中,并且您知道在执行该语句之前必须检索整个结果集,请使用默认结果集。仅当需要游标操作来支持应用程序的功能时,或者可能只检索部分结果集时,才使用服务器游标。
我不是 Oracle DBA,所以我无法真正说出实现的不同之处。但是,从编程的角度来看,基于集合的操作几乎总是比在游标中处理结果要快。
我一直被告知游标是邪恶的,但 MS SQL Server 大师总是告诉我,因为它的性能很差。关于 Oracle 的 PL/SQL ,我发现这句话说何时使用游标:
不使用游标会导致重复解析。如果不使用绑定变量,则对所有 SQL 语句进行硬解析。这对性能有一个数量级的影响,而且完全不可扩展。将游标与打开游标并多次执行的绑定变量一起使用。对生成动态 SQL 的应用程序持怀疑态度。
由于游标是在每个操作上隐式创建 的,因此在需要时使用它们似乎并没有那么惩罚性能:)
请记住,Oracle 的实现更接近 Postgres 而不是 Sybase(MS SQL Server 的起源),因此不同任务的性能会有所不同。如果可以,请避免在可以交换后端的系统上进行性能调整,如果您需要同时使用两者,请选择最小公分母。/tangential_topic
我相信有人可以更详细地解释,但基本上归结为 SQL 服务器中的游标很慢。
其他答案正确地指出了游标的性能问题,但他们没有提到 SQL 和关系数据库最擅长基于集合的操作,而游标基本上用于迭代操作。有一些操作(在更广泛的意义上)使用游标更容易执行,但是在使用 SQL 时,您应该始终考虑使用数据集。游标经常被滥用,因为编码人员没有掌握如何使用基于集合的操作来执行任务。