2013-08-12 12 views
9

クエリ結果のデータベースサイズのページ付けを作成しようとしています。 SQL Server 2012がOFFSET/FETCHを提供しているので、私はそれを使用しています。しかし、クエリに文を追加すると、10倍の時間がかかります。SQL Server 2012でFulltextでOFFSET/FETCHを使用するとパフォーマンスが低下する

クエリ:

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 

まずクエリ47秒で3秒、秒1で結果を返します。実行計画は完全に私には意味をなさないものを、異なっており、第二のコストはわずか7%として評価されています

Execution plan

私は改ページのパフォーマンスを改善する方法を助ける必要があります。

+1

+1、それをaksing誰ずに計画を説明し、これは追加だけfactyouの外に:第二、その一時テーブルに最初のクエリの結果を入れ、order by ... offset fetch nextのためにそれを使用しているため実際にはT-SQLでの問題のページ付けが頻繁に行われます – Najzero

答えて

2

スキーマやデータを手元に置いておく必要はありません。 3秒間にできることが少なくとも1つあります。最初のクエリで47秒。この質問へ

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

あなたのソリューションはページングなしで結果を返すのと同じスピードで動作します。 – adek

+0

他の人のために:ここで説明するように、SQL Serverの古いページネーションメソッドが見つかりました。http://www.mssqltips.com/sqlservertip/2696/comparing-performance-for-different-sql-server-paging-methods/ 私はそれらをテストしてみた、その結果は以下のとおりです。 1. SQL 2000の方法(アイデンティティを持つ一時テーブル):32秒 2. SQL 2005の方法(ROW_NUMBERとのCTE()):47秒 だから、FETCH NEXT使用一時テーブルなしでは、すべての中で最も遅いソリューションです。 – adek

+0

私はこれが適切な解決策ではないと考えています。あなたはまだ全ての結果を容器に収めていて、行を取って飛ばしています。しかし、フルテキスト検索の結果は、最初はすべての結果を得ようとしています。そして、あなたはこれらの結果を切り捨てています。私はcontainstableが 'czarny'、10)を追加するだけでトップのものを取る方法があることを知っているが、私はこれをスキップする方法を考え出していない – WtFudgE

関連する問題