2011-02-09 2 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? –

ответ

2

Для расчета среднего значения требуется сканирование таблицы, так как вы должны суммировать значения и затем делиться на количество (соответствующих) строк. Это, в свою очередь, означает, что вы много сканируете; это медленно. Вы можете рассчитать средние значения и сохранить их? Это позволит вашему запросу использовать эти предварительно вычисленные значения. (Да, это денормализует данные, но часто требуется денормализация для производительности, существует компромисс между производительностью и минимальными данными.)

Возможно, было бы целесообразно использовать временную таблицу в качестве хранилища средних значений.

+0

Мы уже говорили об этом, но мы надеялись, что кто-то узнает решение, которое не нужно было бы делать. –

+0

@Frederik: Я понимаю, но если вам нужна информация, вы * нуждаетесь в ней. Смягчение - самый простой подход. –

Смежные вопросы