2013-08-12 14 views
9

Sto provando a scrivere una paginazione delle dimensioni del database dei risultati della query. Poiché SQL Server 2012 offre OFFSET/FETCH, lo sto utilizzando. Ma dopo aver aggiunto la dichiarazione alla mia richiesta, ci vuole 10 volte di più.Rallentamento delle prestazioni quando si utilizza OFFSET/FETCH con fulltext in SQL Server 2012

Le query:

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 

First query restituisce risultati in 3 secondi, la seconda in 47 secondi. piano di esecuzione sono diverse, e il costo del secondo viene valutato solo il 7%, ciò che rende del tutto non ha senso per me:

Execution plan

Ho bisogno di aiuto come migliorare le prestazioni del impaginazione.

+1

+1 a questa domanda, appena fuori dal factyou aggiunto un piano spiegare senza che nessuno poter richiedere per esso e questo è in realtà un problema di impaginazione in T-SQL incontra molto spesso – Najzero

risposta

2

È difficile consigliare senza avere gli schemi e i dati in mano. C'è almeno una cosa che dovresti essere in grado di fare con quei 3 secondi. per la prima query e 47 secondi. per la seconda, che viene messa risultati della prima query in tabella temporanea e quindi utilizzare per 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

la tua soluzione funziona bene, stessa velocità del risultato di ritorno senza impaginazione. – adek

+0

Solo per gli altri: ho trovato metodi di impaginazione più vecchi per SQL Server, come descritto qui: http://www.mssqltips.com/sqlservertip/2696/comparing-performance-for-different-sql-server-paging-methods/ li ho provato, ed i risultati sono: 1. SQL 2000 metodo (tabella temporanea con l'identità): 32 secondi 2. SQL 2005 il metodo (CTE con ROW_NUMBER()): 47 secondi Quindi, utilizzando FETCH AVANTI senza tabella temporanea è la soluzione più lenta di tutti. – adek

+0

Non ritengo che questa sia una soluzione adeguata visto che ci si sta ancora unendo a TUTTI i risultati del containtable e quindi prendendo e saltando le righe. Ma il risultato della ricerca di testo completo è ancora in grado di ottenere tutti i risultati, e quindi stai tagliando questi risultati. So che containtable ha un modo di prendere i migliori solo aggiungendo 'czarny', 10), ma non ho capito come saltare questo – WtFudgE

Problemi correlati