使用 FAST_FORWARD 定义游标有什么好处?性能更好吗?为什么?
5 回答
MSDN的定义是:
指定启用了性能优化的 FORWARD_ONLY、READ_ONLY 游标。如果同时指定了 SCROLL 或 FOR_UPDATE,则无法指定 FAST_FORWARD。FAST_FORWARD 和 FORWARD_ONLY 是互斥的;如果指定了一个,则无法指定另一个。
我加粗了关键位。它可以支持这些“性能优化”,因为它不需要支持通过游标进行多方向迭代(FORWARD_ONLY),也不支持修改(READ_ONLY)。
当然,如果您根本不需要使用游标,那么即使使用此选项也不会使用游标。如果您可以使用基于集合的方法来完成相同的任务,请改为这样做 - 这是我真正想强调的一点。
FAST_FORWARD - 指定游标将是 FORWARD_ONLY 和 READ_ONLY 游标。FAST_FORWARD 游标在 SQL Server 上产生的开销最少。
来源:点击这里
FAST_FORWARD
指定它是FORWARD_ONLY
and ,这READ_ONLY
意味着它使用最少的服务器资源来处理它......所以是的,为了性能。
FAST_FORWARD
- 指定启用了性能优化的 FORWARD_ONLY、READ_ONLY 游标。如果同时指定了 SCROLL 或 FOR_UPDATE,则无法指定 FAST_FORWARD。
请记住,FAST_FORWARD 是 DYNAMIC ... FORWARD_ONLY 您可以与 STATIC 游标一起使用。
尝试在万圣节问题上使用它,看看会发生什么!!!
IF OBJECT_ID('Funcionarios') IS NOT NULL
DROP TABLE Funcionarios
GO
CREATE TABLE Funcionarios(ID Int IDENTITY(1,1) PRIMARY KEY,
ContactName Char(7000),
Salario Numeric(18,2));
GO
INSERT INTO Funcionarios(ContactName, Salario) VALUES('Fabiano', 1900)
INSERT INTO Funcionarios(ContactName, Salario) VALUES('Luciano',2050)
INSERT INTO Funcionarios(ContactName, Salario) VALUES('Gilberto', 2070)
INSERT INTO Funcionarios(ContactName, Salario) VALUES('Ivan', 2090)
GO
CREATE NONCLUSTERED INDEX ix_Salario ON Funcionarios(Salario)
GO
-- Halloween problem, will update all rows until then reach 3000 !!!
UPDATE Funcionarios SET Salario = Salario * 1.1
FROM Funcionarios WITH(index=ix_Salario)
WHERE Salario < 3000
GO
-- Simulate here with all different CURSOR declarations
-- DYNAMIC update the rows until all of then reach 3000
-- FAST_FORWARD update the rows until all of then reach 3000
-- STATIC update the rows only one time.
BEGIN TRAN
DECLARE @ID INT
DECLARE TMP_Cursor CURSOR DYNAMIC
--DECLARE TMP_Cursor CURSOR FAST_FORWARD
--DECLARE TMP_Cursor CURSOR STATIC READ_ONLY FORWARD_ONLY
FOR SELECT ID
FROM Funcionarios WITH(index=ix_Salario)
WHERE Salario < 3000
OPEN TMP_Cursor
FETCH NEXT FROM TMP_Cursor INTO @ID
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT * FROM Funcionarios WITH(index=ix_Salario)
UPDATE Funcionarios SET Salario = Salario * 1.1
WHERE ID = @ID
FETCH NEXT FROM TMP_Cursor INTO @ID
END
CLOSE TMP_Cursor
DEALLOCATE TMP_Cursor
SELECT * FROM Funcionarios
ROLLBACK TRAN
GO
(我知道这是旧的,但为了后代)
只是为了说明“fast_forward”和“forward_only/read_only”游标,区别在于游标计划的使用。
FO/RO
游标总是使用动态查询计划——对于大多数应用程序来说,这已经足够了。然而,即使是好的动态计划也几乎永远不会像静态计划那样好。
FF
如果更好,游标将使用静态计划,并且永远不会降级游标计划(主要是“...启用性能优化。”指的是)。
一般来说,动态计划更适合小结果集(“低目标”)游标,反之亦然。