Cursor(游标)在数据库操作中效率较低,主要原因在于其逐行处理的工作方式与数据库引擎基于集合(Set)的操作模型相悖。数据库系统(如 Oracle, SQL Server, MySQL, PostgreSQL)天生擅长处理批量数据,而非逐行迭代。
以下是导致 Cursor 效率低下的最核心原因:
这是最根本的原因。
SELECT * FROM table WHERE id > 10 时,数据库引擎会一次性规划并执行整个数据集的获取。for 循环一样,一行一行地读取、处理、提交。当应用程序(如 Java, Python, C#)使用 Cursor 与数据库交互时,会产生巨大的开销。
FETCH 一行数据,应用程序都需要向数据库服务器发送一次请求,数据库处理后再返回结果。如果是网络应用,这涉及一次网络往返延迟(Round-trip)。许多 Cursor(特别是更新游标)为了保持数据一致性,会在读取数据时对行或页加锁。
ORA-01555 (Snapshot too old) 等错误。打开一个 Cursor 通常需要数据库在内存或临时表空间(如 SQL Server 的 TempDB)中维护状态。
数据库查询优化器非常智能,可以决定使用索引、改变连接顺序等。但一旦使用 Cursor:
DECLARE -> OPEN -> FETCH -> CLOSE 的流程,难以进行复杂的执行计划优化。假设你需要给 Employees 表中所有工资低于 5000 的员工加薪 10%。
DECLARE cur CURSOR FOR SELECT id, salary FROM Employees WHERE salary < 5000;
-- 循环开始
FETCH NEXT FROM cur...
UPDATE Employees SET salary = salary * 1.1 WHERE id = @id; -- 逐行更新
-- 循环结束
UPDATE Employees SET salary = salary * 1.1 WHERE salary < 5000;
虽然 Cursor 效率低,但在某些无法用集合逻辑表达的场景下,它是必要的(虽然通常仍有更好的替代方案,如窗口函数):
如果你发现过程很慢且涉及 Cursor,请尝试以下优化:
UPDATE、INSERT 或 MERGE 语句。WITH 子句或子查询一次性处理数据。SELECT *。FAST_FORWARD / READ_ONLY: 明确指定游标属性,告诉数据库不需要更新,减少锁定开销(例如在 SQL Server 中使用 FAST_FORWARD)。DECLARE CURSOR 的查询中尽可能通过 WHERE 过滤掉不需要的数据。CROSS APPLY 或 STRING_AGG 等窗口函数。generate_series 或数组操作。总结: Cursor 效率低是因为它破坏了数据库的核心优势——批量处理。除非迫不得已,否则应始终避免使用 Cursor。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。