2016-08-02 15 views
1

I持って、次のDBのテーブル:複雑なSQLクエリ、大きなデータベース

BOOKS

book_id | date | library_id 
1  | 06 | 34 
2  | 02 | 12 
3  | 04 | 34 
4  | 09 | 66 

LIBRARY

library_id | adress | owner 
1   | "cxc" | "andf" 
2   | "mkm" | "kla" 
3   | "ass" | "pol" 
4   | "kon" | "ger" 

PAGESLLV

page_id | book_id | text 
4  | 4  | "YYYY ss" 
3  | 1  | "FFF as" 
3  | 1  | "FDER fs" 
3  | 2  | "GRG xx"" 

PAGESKYK

page_id | book_id | text 
1  | 1  | "ddadad" 
2  | 3  | "xcvxcv" 
1  | 3  | "adad" 
2  | 2  | "ddddweg" 

PAGESLOO

page_id | book_id | text 
6  | 5  | "VV" 
5  | 2  | "CCC" 
6  | 2  | "ZZ" 
7  | 3  | "AA" 

とDBに関するいくつかの情報:

1)全ての書籍が多くのページ

example: 

Book with id 622 has: 
234 pages with id 45, 
120 pages with id 23, 
1 page with id 11, 
1 page with id 31, 

Book with id 322 has: 
1 page with id 67, 
1 page with id 88 

2を持っている)すべての本があり1つのlibrary_id

を持っていますPAGE___という名前の9つのテーブルです(___は"LLV"のようなもの) 約2400万レコードがあります。

今、私は、特定のIDを持つすべてのページを含むすべての書籍(ライブラリのアドレスを含む)を抽出するためにクエリを作成する必要があります。

ので、例えば:

Book with id 622 has: 
234 pages with id 45, 
120 pages with id 88, 
1 page with id 11, 
1 page with id 23, 

Book with id 13 has: 
234 pages with id 88, 
120 pages with id 23, 
1 page with id 11, 
1 page with id 15, 
2 pages with id 56, 

Book with id 322 has: 
1 page with id 23, 
1 page with id 88 

、彼らは私に配列[88,23,11,15]を得るとid 13との唯一の本が有効であるので、私は

book_id | date | library_adress | library_owner | 
13  | ~~~~ | ~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~| 

を返します。

私は今の私のSQLは、Microsoft SQL Server 2008の

を使用しています:

'with p1 as (
    select distinct podv.Book_id, podv.Page_Id 
    from PAGESLLV podv with (nolock) 
    where podv.Page_Id in (' + @Ids + ') 
    union all 
    select distinct psv.Book_id, psv.Page_Id 
    from PAGESXXN psv with (nolock) 
    where psv.Page_Id in (' + @Ids + ') 
    union all 
    select distinct psav.Book_id, psav.Page_Id 
    from PAGESTTY psav with (nolock) 
    where psav.Page_Id in (' + @Ids + ') 
    union all 
    select distinct psx.Book_id, psx.Page_Id 
    from PASGESPOO psx with (nolock) 
    where psx.Page_Id in (' + @Ids + ') 
    union all 
    select distinct pv.Book_id, pv.Page_Id 
    from PAGESMIO pv with (nolock) 
    where pv.Page_Id in (' + @Ids + ') 
    union all 
    select distinct tpb.Book_id, tpb.Page_Id 
    from PAGESQWW tpb with (nolock) 
    where tpb.Page_Id in (' + @Ids + ')), 
p2 as (select p1.Book_id 
    from p1 
    group by p1.Book_id 
    having COUNT(p1.Book_id) = ' + @Amount + ') 
select top 1000 
    r.Book_id, 
    r.date, 
    v.adress, 
    v.owner, 
    from Books r with (nolock) 
    inner join p2 with (nolock) on (r.Book_id = p2.Book_id) 
    join Library v with (nolock) on (r.library_id = v.library_id) 
    order by r.Book_id') 

を、それは動作しますが、遅すぎる

任意の助けてくれてありがとう、と私の英語力のために残念。

+2

だから、あなたがこれまでにしようとしているものを.... – logixologist

+0

http://pastebin.com/1JTbQJjz それは今あまりにも遅いために働く:/ –

+0

RDBMS(ベンダーおよびバージョン)を追加してくださいとecpected出力を追加してください**与えられたサンプルデータにフィッティング**! – Shnugo

答えて

0

おそらくそれは遅くなりますが、それらのページテーブルのいくつかには、page_idのインデックスがありません。

したがって、これらのPAGE表の全表スキャンでは処理が遅くなります。

おそらくpage_idの単なるインデックスよりも優れているのは、book_idとpage_idの組み合わせインデックスです。

したがって、以下のSQLは重要ではありません。
同じパフォーマンスを与えるばかげた書き直し。

IF OBJECT_ID('tempdb..#tmpPageIds') IS NOT NULL DROP TABLE #tmpPageIds; 

CREATE TABLE #tmpPageIds (id int primary key); 
insert into #tmpPageIds values (88),(23),(11),(15),(56); 

DECLARE @Amount INT = (select count(*) from #tmpPageIds); 

select 
b.book_id, 
b.date, 
l.adress as library_adress, 
l.owner as library_owner 
from (
    select book_id 
    (
    select distinct book_id, page_id from PAGESLLV t with (nolock) 
    join #tmpPageIds tmp on (t.page_id = tmp.id) 
    union all 
    select distinct book_id, page_id from PAGESXXN t with (nolock) 
    join #tmpPageIds tmp on (t.page_id = tmp.id) 
    union all 
    select distinct book_id, page_id from PAGESTTY t with (nolock) 
    join #tmpPageIds tmp on (t.page_id = tmp.id) 
    union all 
    select distinct book_id, page_id from PASGESPOO t with (nolock) 
    join #tmpPageIds tmp on (t.page_id = tmp.id) 
    union all 
    select distinct book_id, page_id from PAGESMIO t with (nolock) 
    join #tmpPageIds tmp on (t.page_id = tmp.id) 
    union all 
    select distinct book_id, page_id from PAGESQWW t with (nolock) 
    join #tmpPageIds tmp on (t.page_id = tmp.id) 
) q1 
    group by book_id 
    having count(distinct page_id) = @Amount 
) q2 
join BOOKS b on (q2.book_id = b.book_id) 
join LIBRARY l on (b.library_id = l.library_id); 
+0

私はこのデータベースのスキーマを変更することはできません。その巨大で私のプロジェクトは、このdbを使用するソフトウェアのごく一部です。 –

+0

page_idは、このテーブルPAGE___に同じIDを持つページが多数あるため、インデックスできません –

+0

Uhm、インデックスは一意である必要はありません。したがって、(page_id、book_id)に特別な一意でないインデックスを追加することは可能です。ただし、インデックスを追加することはオプションではない場合は、クエリを高速化する方法がわかりません。したがって、パーティション化はオプションではありません。少なくとも、テーブルのDDLをチェックして、現在のインデックスを確認することができます。 – LukStorms

0

こんにちは、これは、並列に動作しますどれだけ見て遊んでされて。だから私は、あなたがBookIdは、各テーブルのインデックスは(おそらく最高のそれをクラスタに)、あなたがすべきであることを確認している場合

With CTE(RealID,ID,Name) as (
select * from Table_1a 
Union all 
select * from Table_1b 
) 

select * from CTE where RealID in (1,43) 

は、CTEはあなたの例では、すべてのページの表である

場合は、次のように最善のアプローチがあると信じて非常にまともな実行計画を参照してください。私はテーブルごとに140kレコードをテストしただけですが、それは私のために実行されます。