2009-06-09 6 views
2

J'ai une table avec 15 colonnes et 6,5 millions d'enregistrements. J'ai besoin d'accéder à cette table du côté C# avec l'aide de pagination. J'ai écrit un SP, mais il faut environ 1,30 minutes pour récupérer les données. ici est mon stocké Proc -Paging à travers une grande table en sql 2005

Create Proc demo 
(
@startRowIndex int, 
@maximumRows int 
) 
AS 

DECLARE @first_id int, @startRow int 

SET @startRowIndex = (@startRowIndex - 1) * @maximumRows 

IF @startRowIndex = 0 
SET @startRowIndex = 1 

SET ROWCOUNT @startRowIndex 

SELECT @first_id = RecordID FROM edd_business_listings_05282009 ORDER BY RecordID 

PRINT @first_id 

SET ROWCOUNT @maximumRows 

SELECT * FROM edd_business_listings_05282009 WHERE 
RecordID >= @first_id 
ORDER BY RecordID 

SET ROWCOUNT 0 

Est-ce que quelqu'un sait une façon de faire cette course plus rapide.

+1

Nous ne ferions que deviner sans la définition de la table (CREATE TABLE, s'il vous plaît), les clés et les index. – RBarryYoung

+0

Un index non cluster sur RecordID, même s'il s'agit déjà de l'index clusterisé, aiderait avec SELECT @first_id = RecordID .... –

+0

Si RecordID est séquentiel, un index clusterisé fonctionnerait beaucoup meilleur. – jfar

Répondre

2

Votre application peut-elle envoyer le dernier RecordID?

Rend le travail frontal plus difficile.

Créer Proc demo (@startRowID int, int @maximumRows) AS

SET ROWCOUNT @maximumRows

SELECT * FROM edd_business_listings_05282009 OÙ RecordID> @startRowID ORDER BY RecordID

SET ROWCOUNT 0

+0

@jfar: SET ROWCOUNT @maximumRows garantit qu'il retournera les 20 lignes suivantes, si elles existent. Non? –

+0

à droite, SET ROWCOUNT ne serait pas affecté par les enregistrements manquants. –

0

Si vous utilisez SQL Server 2005, vous pouvez essayer

SELECT field1, field2, fieldN 
FROM  (SELECT ROW_NUMBER() OVER (ORDER BY RecordID) AS Row, 
      field1, field2, fieldN FROM edd_business_listings_05282009) 
      AS ListingsWithRowNumbers 
WHERE Row >= @startRowIndex AND Row <= @startRowIndex + @maximumRows 

Mais de toute façon, essayez de repenser cette architecture. À quoi sert d'afficher des millions d'enregistrements (même paginés) dans l'interface utilisateur? Vous pouvez essayer de limiter le nombre d'enregistrements et d'interroger uniquement un sous-ensemble au début ...

+0

Cela ne fonctionnera pas après la première page d'enregistrements, une fois @startRowIndex> @maximumRows. –

+0

oups. copié la mauvaise version. Je supprime la clause TOP. –

0

Essayez de placer un index dans la colonne RecordId. Ce que je pense est que vous faites une analyse de table entière avant que le rowcount ne soit en place afin que Sql puisse tout commander. Si vous avez déjà un index que quelque chose d'autre est le problème. J'ai fait cette même requête sur des tables avec deux fois le nombre d'enregistrements et mon temps d'exécution n'est jamais passé au-dessus de 2 secondes. Utiliser ROWCOUNT ou Row_Number() devrait techniquement accomplir les mêmes performances mais j'utiliserais Row_Number() car c'est un moyen plus moderne de le faire et définir rowcount a beaucoup plus de complexités que Row_Number() Je ne vais pas entrer.

1

Essayez d'utiliser ROW_NUMBER dans SQL 2005: http://www.4guysfromrolla.com/webtech/010406-1.shtml

procédure comme celle-ci contribuerait à:

CREATE PROCEDURE dbo.GetListingPaged 
(
    @StartRowIndex int, 
    @MaximumRows int 
) 
AS 
    SELECT 
     RecordID, 
     Field2 -- Not * 
    FROM 
    (
    SELECT 
     RecordID, 
     Field2 -- Not * 
     ROW_NUMBER() OVER (ORDER BY RecordID) AS RowRank 
    FROM edd_business_listings_05282009 
    ) AS ListingWithRowNumbers 
    WHERE 
     RowRank > @StartRowIndex 
    AND 
     RowRank <= (@StartRowIndex + @MaximumRows) 

GO 
+0

Je voudrais voir le temps de réponse vs la profondeur de pagination avec cette approche. –

1

OK, bien sûr, voici ma conjecture aussi:

Create Proc demo (@startRowIndex int, @maximumRows int) AS 
DECLARE @first_id int, @startRow int 
SET @startRowIndex = (@startRowIndex - 1) * @maximumRows 

IF @startRowIndex = 0 SET @startRowIndex = 1 

SELECT TOP (@maximuRows) 
{'all columns except N'} 
FROM (
    Select *, ROW_NUMBER() Over(Order by RecordID) as N 
    from edd_business_listings_05282009 
    ) As t 
WHERE N >= @startRowIndex 
ORDER BY RecordID 
1

La meilleure solution est va dépendre lourdement de

1.donc souvent les données changent

2.how souvent sproc est appelée et la profondeur d'un utilisateur typicall la page et

3.how beaucoup de latence (le cas échéant), vous pouvez accepter dans l'ordre d'être mis à jour.

Souvent dans un backend de site Web vos utilisateurs utilisent seulement les premières pages, mais google bot peut claquer vos pages profondes et donc claquer votre cpu. Il est généralement bon de ne prendre en charge cette commande en direct que jusqu'à un certain point (par exemple, row_number() pour les premières centaines ou milliers de lignes), puis de passer à une liste dénormalisée de commandes rafraîchies sur un intervalle (peut-être horaire).

Questions connexes