Come ha suggerito Martin in un commento sotto la domanda, il problema è che il server SQL non spinge correttamente il predicato dalla clausola WHERE - vedi il link nel suo commento.
Alla fine ho creato una funzione con valori di tabella definita dall'utente e l'ho usata con l'operatore CROSS APPLY per creare la vista.
Vediamo la soluzione stessa.
Funzione definita dall'utente con valori di tabella
CREATE FUNCTION [dbo].[TestFunction] (@Id INT)
RETURNS TABLE
AS
RETURN
(
WITH
Hierarchy (Id, ParentId, Data, Depth)
AS(
SELECT Id, ParentId, NULL AS Data, 0 AS Depth FROM Test Where Id = @Id
UNION ALL
SELECT h.Id, t.ParentId, COALESCE(h.Data, t.Data), Depth + 1 AS Depth
FROM Hierarchy h
INNER JOIN Test t ON t.Id = h.ParentId
)
SELECT * FROM Hierarchy
)
Visualizza
CREATE VIEW [dbo].[TestView]
AS
SELECT t.Id, t.ParentId, f.Data, f.Depth
FROM
Test AS t
CROSS APPLY TestFunction(Id) as f
Query con costante
SELECT * FROM TestView WHERE Id = 69
Query con parametro
DECLARE @Id INT
SELECT @Id = 69
SELECT * FROM TestView WHERE Id = @Id
La query con il parametro viene eseguita sostanzialmente alla stessa velocità della query con la costante.
Grazie Martin e anche per gli altri!