2013-08-12 4 views
9

Je tente d'écrire une pagination de la taille de la base de données des résultats de la requête. Comme SQL Server 2012 offre OFFSET/FETCH, je l'utilise. Mais après avoir ajouté l'instruction à ma requête, cela prend 10 fois plus de temps.Lenteur des performances lors de l'utilisation de OFFSET/FETCH avec Fulltext dans SQL Server 2012

Les requêtes:

SELECT 
    p.ShopId, 
    count(1) as ProductsQuantity, 
    MIN(LastPrice) as MinPrice, 
    MAX(LastPrice) as MaxPrice 
FROM Product2 p WITH (NOLOCK) 
INNER JOIN 
    CONTAINSTABLE(Product2, ProductName, 'czarny') AS KEY_TBL 
ON KEY_TBL.[key]=p.Id 
WHERE 
    (p.LastStatus > 0 OR p.LastStatus = -1) 
GROUP BY p.ShopId 
ORDER BY p.ShopId asc 



SELECT 
    p.ShopId, 
    count(1) as ProductsQuantity, 
    MIN(LastPrice) as MinPrice, 
    MAX(LastPrice) as MaxPrice 
FROM Product2 p WITH (NOLOCK) 
INNER JOIN 
    CONTAINSTABLE(Product2, ProductName, 'czarny') AS KEY_TBL 
ON KEY_TBL.[key]=p.Id 
WHERE 
    (p.LastStatus > 0 OR p.LastStatus = -1) 
GROUP BY p.ShopId 
ORDER BY p.ShopId asc 
OFFSET 10 ROWS 
FETCH NEXT 10 ROWS ONLY 

Première requête retourne les résultats en 3 secondes, la seconde en 47 secondes. Plan d'exécution sont différentes, et le coût de la seconde est évaluée seulement 7%, ce qui rend tout à fait aucun sens pour moi:

Execution plan

Je dois aider comment améliorer les performances de la mise en page.

+1

+1 à cette question, juste en dehors du factyou ajouté un plan expliquer sans que personne aksing pour elle et c'est en fait une pagination de problème dans les rencontres T-SQL assez souvent – Najzero

Répondre

2

Il est difficile de vous conseiller sans avoir votre schéma et vos données en main. Il y a au moins une chose que vous devriez être capable de faire avec ces 3 secondes. pour la première requête et 47 sec. pour la deuxième, qui est mis résultats de la première requête dans la table temporaire, puis l'utiliser pour order by ... offset fetch next:

create table #tmp (Id int not NULL, Quantity int, MinPrice decimal(10,4), MaxPrice decimal(10,4), primary key clustered (Id)) 

insert into #tmp 
SELECT 
    p.ShopId, 
    count(1) as ProductsQuantity, 
    MIN(LastPrice) as MinPrice, 
    MAX(LastPrice) as MaxPrice 
FROM Product2 p WITH (NOLOCK) 
INNER JOIN 
    CONTAINSTABLE(Product2, ProductName, 'czarny') AS KEY_TBL 
ON KEY_TBL.[key]=p.Id 
WHERE 
    (p.LastStatus > 0 OR p.LastStatus = -1) 
GROUP BY p.ShopId 

select ShopId, ProductsQuantity, MinPrice, MaxPrice 
from #tmp 
ORDER BY ShopId asc 
OFFSET 10 ROWS 
FETCH NEXT 10 ROWS ONLY 
+0

votre solution fonctionne bien, même vitesse que le résultat de retour sans pagination. – adek

+0

Juste pour les autres: j'ai trouvé des méthodes de pagination plus anciennes pour SQL Server, comme décrit ici: http://www.mssqltips.com/sqlservertip/2696/comparing-performance-for-different-sql-server-paging-methods/ Je les ai testé, et les résultats sont les suivants: 1. méthode SQL 2000 (table temporaire avec l'identité): 32 secondes 2. méthode SQL 2005 (CTE avec ROW_NUMBER()): 47 secondes donc, en utilisant FETCH SUIVANT sans table temporaire est la solution la plus lente de tous. – adek

+0

Je ne considère pas cela comme une bonne solution car vous vous joignez toujours à TOUS les résultats du containstable, puis prenez et ignorez les lignes. Mais le résultat de la recherche en texte intégral va tout d'abord obtenir tous les résultats, et ensuite vous coupez ces résultats. Je sais que containstable a un moyen de prendre les meilleurs en ajoutant 'czarny', 10), mais je n'ai pas compris comment sauter ce – WtFudgE

Questions connexes