J'ai une table Employee
qui contient un million d'enregistrements. J'ai suivi SQL pour paginer des données dans une application Web. Cela fonctionne bien. Cependant, ce que je vois comme un problème est - la table dérivée tblEmployee
sélectionne tous les enregistrements de la table Employee
(pour créer les valeurs MyRowNumber
).
Je pense que cela entraîne la sélection de tous les enregistrements de la table Employee
.
Est-ce que ça marche vraiment? Ou SQL Server est-il optimisé pour sélectionner uniquement les 5 enregistrements de la table Employee
d'origine?
DECLARE @Index INT;
DECLARE @PageSize INT;
SET @Index = 3;
SET @PageSize = 5;
SELECT * FROM
(SELECT ROW_NUMBER() OVER (ORDER BY EmpID asc) as MyRowNumber,*
FROM Employee) tblEmployee
WHERE MyRowNumber BETWEEN ( ((@Index - 1) * @PageSize )+ 1) AND @Index*@PageSize
Une alternative au test pourrait être:
;WITH x AS (SELECT EmpID, k = ROW_NUMBER() OVER (ORDER BY EmpID) FROM dbo.Emp)
SELECT e.columns
FROM x INNER JOIN dbo.Emp AS e
ON x.EmpID = e.EmpID
WHERE x.k BETWEEN (((@Index - 1) * @PageSize) + 1) AND @Index * @PageSize
ORDER BY ...;
Oui, vous frappez la table deux fois, mais dans le CTE où vous scannez la table entière, vous ne saisissez que la clé, pas TOUTES les données. Mais vous devriez vraiment regarder cet article:
http://www.sqlservercentral.com/articles/T-SQL/66030/
Et la discussion de suivi:
http://www.sqlservercentral.com/Forums/Topic672980-329-1.aspx
Dans SQL Server 2012, vous pouvez bien sûr utiliser le nouveau OFFSET
/FETCH NEXT
syntaxe:
;WITH x AS
(
SELECT EmpID FROM dbo.Emp
ORDER BY EmpID
OFFSET @PageSize * (@Index - 1) ROWS
FETCH NEXT @PageSize ROWS ONLY
)
SELECT e.columns
FROM x INNER JOIN dbo.Emp AS e
ON x.EmpID = e.EmpID
ORDER BY ...;
J'ai également blogué à ce sujet plus en détail ici:
Bien que vous ne connaissiez peut-être pas le mécanisme qui le sous-tend, vous pouvez le tester vous-même en comparant les performances de votre requête pour: sélectionner * dans Employé.
Les versions les plus récentes de SQL Server font un assez bon travail d'optimisation, mais cela peut dépendre de plusieurs facteurs.
Le fonctionnement de votre fonction ROW_NUMBER sera déterminé par la clause Order By. Dans votre exemple, la plupart penseraient que EmpID est la clé primaire.
Il y a des clauses où qui sont si complexes et/ou mal codées ou indexées, il vaut peut-être mieux renvoyer tout l'ensemble de données (c'est rare et peut être corrigé). L'utilisation de BETWEEN présente des problèmes.
Avant de supposer qu'il serait préférable de renvoyer toutes les lignes à votre application et de la laisser comprendre, vous devez travailler sur l'optimisation de votre requête. Vérifiez les estimations. Demandez à l'analyseur de requêtes. Testez quelques alternatives.
Je sais que la question concerne row_number () mais je veux ajouter une nouvelle fonctionnalité de sql server 2012. Dans sql server 2012, la nouvelle fonctionnalité OFFSET Fetch a été introduite et elle est très rapide que row_number (). Je l'ai utilisé et cela me donne de bons résultats j'espère que vous remplissez également la même expérience.
J'ai trouvé un exemple sur http://blogfornet.com/2013/06/sql-server-2012-offset-use/
ce qui est utile. J'espère que cela vous aidera aussi à mettre en œuvre de nouvelles fonctionnalités ....