2011-02-09 97 views
2

對於作者概述,我們正在尋找一個查詢,它將顯示所有作者,包括他們的最佳作品。這個查詢的問題是它缺乏速度。只有大約1500位作者,並且查詢確實會生成概覽,目前需要20秒。如何快速創建子查詢

主要問題似乎是生成每人所有書籍的平均評分。 通過選擇下面的查詢,它仍然是相當快的

select 
    person.id as pers_id, 
    person.firstname, 
    person.suffix, 
person.lastname, 
    thriller.title, 
    year(thriller.orig_pubdate) as year, 
    thriller.id as thrill_id, 
    count(user_rating.id) as nr, 
    AVG(user_rating.rating) as avgrating 
from 
    thriller 
inner join 
    thriller_form 
    on thriller_form.thriller_id = thriller.id 
inner join 
    thriller_person 
    on thriller_person.thriller_id = thriller.id 
    and thriller_person.person_type_id = 1 
inner join 
    person 
    on person.id = thriller_person.person_id 
left outer join 
    user_rating 
    on user_rating.thriller_id = thriller.id 
    and user_rating.rating_type_id = 1 
where thriller.id in 
    (select top 1 B.id from thriller as B 
    inner join thriller_person as C on B.id=C.thriller_id 
    and person.id=C.person_id) 
group by 
    person.firstname, 
    person.suffix, 
    person.lastname, 
    thriller.title, 
    year(thriller.orig_pubdate), 
    thriller.id, 
    person.id 
order by 
    person.lastname 

但是,如果我們的子查詢多一點用平均收視它需要一個完整的20秒產生一個結果選擇書複雜。 查詢將被如下:

select 
    person.id as pers_id, 
    person.firstname, 
    person.suffix, 
    person.lastname, 
    thriller.title, 
    year(thriller.orig_pubdate) as year, 
    thriller.id as thrill_id, 
    count(user_rating.id) as nr, 
    AVG(user_rating.rating) as avgrating 
from 
    thriller 
inner join 
    thriller_form 
    on thriller_form.thriller_id = thriller.id 
inner join 
    thriller_person 
    on thriller_person.thriller_id = thriller.id 
    and thriller_person.person_type_id = 1 
inner join 
    person 
    on person.id = thriller_person.person_id 
left outer join 
    user_rating 
    on user_rating.thriller_id = thriller.id 
    and user_rating.rating_type_id = 1 
where thriller.id in 
    (select top 1 B.id from thriller as B 
    inner join thriller_person as C on B.id=C.thriller_id 
    and person.id=C.person_id 
    inner join user_rating as D on B.id=D.thriller_id 
    group by B.id 
    order by AVG(D.rating)) 
group by 
    person.firstname, 
    person.suffix, 
    person.lastname, 
    thriller.title, 
    year(thriller.orig_pubdate), 
    thriller.id, 
    person.id 
    order by 
    person.lastname 

任何人有一個很好的建議,以加快此查詢?

+0

什麼版本的SQL Server? – 2011-02-09 13:47:32

回答

2

計算平均值需要進行表掃描,因爲您必須總結這些值然後除以(相關)行的數量。這反過來意味着你正在做很多重新掃描;這很慢。你能計算一次平均值並存儲它們嗎?這將讓你的查詢使用這些預先計算的值。 (是的,它使數據非規格化,但是對於性能來說非規範化通常是必要的;在性能和最小數據之間有折衷。)

使用臨時表作爲平均值的存儲可能是合適的。

+0

我們已經在談論這個問題,但我們希望有人會知道一個不需要這樣做的解決方案。 – 2011-02-09 13:53:58