Какой запрос кажется эффективным? - PullRequest
3 голосов
/ 02 сентября 2010

Я хочу знать, какой из 2 запросов ниже: -

Select s.*,
       sm.* 
  from tblStudent s
Inner Join (SELECT studentId,SUM(marks) As Sum
              from tblStudentsMarks  
           Group By studentId) as sm on s.StudentID = sm.StudentID;

... или:

Select s.studentId, 
       s.Name,
       SUM(Marks)
  From tblStudent s
Inner Join tblStudentsMarks sm On s.Studentid = sm.StudentId
  Group By s.studentId, s.Name;

РЕДАКТИРОВАТЬ: -

Оценка запроса 1-го запроса: - http://img28.imageshack.us/img28/166/1stpicd.jpg

Оценка запроса 2-го запроса: - http://img245.imageshack.us/img245/5064/2ndpic.jpg

Заранее спасибо:)

Ответы [ 7 ]

4 голосов
/ 02 сентября 2010

Вы можете запустить их оба и использовать план выполнения для сравнения каждого из них.

3 голосов
/ 02 сентября 2010

После просмотра планов выполнения первый запрос более эффективен.
Оба имеют сканирование таблицы на tblStudentMarks, но процент по первому запросу намного ниже по сравнению со вторым. SORT не идеален, но из-за того, что сканирование таблицы находится в обоих - возможно, легче справиться, добавив индекс.И SORT, и сканирование таблицы можно улучшить, просмотрев индексы ...

2 голосов
/ 02 сентября 2010

Зависит от ваших данных и индексов.Обычно говорят, что SQL Server лучше оптимизирует объединения, чем подзапросы, и, поскольку он также более читабелен (и, следовательно, более удобен в обслуживании и менее подвержен ошибкам), я бы сейчас выбрал вариант 2 (объединение) и посмотрелВы столкнулись с любыми препятствиями в работе.Если это критичный по скорости запрос, я бы попробовал оба и сравнил результаты.Убедитесь, что вы используете реалистичные данные для тестирования.

1 голос
/ 03 сентября 2010

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

CREATE TABLE tblStudent(
studentId INT identity(1,1) primary key,
Name varchar(50),
filler char(2000));

create nonclustered index ix on tblStudent (StudentId, Name);

Insert into tblStudent (Name)
select top 10000 newid()
from sys.objects s1,sys.objects s2,sys.objects s3,sys.objects s4;

CREATE TABLE tblStudentsMarks(
examid int not null
,studentId INT foreign key references tblStudent not null
,marks decimal(5,2) not null
,primary key clustered (studentId, examid))

insert into tblStudentsMarks
select abs(checksum(newid())) as examid, studentId ,abs(checksum(newid()))/10000000 as marks
from tblStudent  cross join (select top 5 1 C from sys.objects) d
where studentid % 3 =0

Дает иной вывод

Execution Plans

Если мы избавимся от *в запросе 1 и замените его на Select s.studentId, s.Name, sm.Sum оба плана запроса получат точно такой же .

0 голосов
/ 18 ноября 2011

Я знаю, что это довольно экстремально, но у меня есть похожий запрос, который я запускаю для некоторых очень больших таблиц.Предполагая, что у вас есть кластеризованный индекс для tblStudent.studentId, это может дать вам лучшие результаты.SQL любит объединения по кластеризованным индексам.О, я бы хотел, чтобы TSQL поддерживал ограничения на производные таблицы, поэтому не пришлось прибегать к #temp.В моем случае производная таблица (ваша первая пробежка за 18 секунд).Ваш второй подход побежал через 20 несколько секунд (по моим данным).И #temp ниже с кластеризованным индексом к кластерному индексу побежал менее чем за 1 секунду.Это мои данные с миллионами строк.Если ваш запрос выполняется менее чем за 1/10 секунды, тогда он не стоит накладных расходов # temp.

    CREATE TABLE #sumMarks ([StudentId] [int] NOT NULL, PRIMARY KEY CLUSTERED ([StudentId] ASC), [MarksSum] [int])
    GO 

    INSERT INTO #sumMarks
    SELECT [studentId], sum(Marks) as [MarksSum] 
    FROM [tblStudentsMarks] with (nolock) 
    group by [tblStudentsMarks].[studentId] 
    ORDER by [tblStudentsMarks].[studentId];
    go
    Select s.studentId, s.Name, sm.[MarksSum]
    From tblStudent s
    Inner Join #sumMarks as sm On s.Studentid = sm.StudentId;
    go

    DROP TABLE #sumMarks;
0 голосов
/ 02 сентября 2010

Чтобы ускорить, не используйте Select *.Попробуйте также Left Join вместо Join (только если дают тот же результат)Выберите тот, который быстрее на вашем производственном сервере (в зависимости от объема данных, фрагментации индекса и селективности индекса оптимизатор запросов может выбрать другой план производства по сравнению с тестовым сервером).При тестировании не забывайте очищать кэш между запусками.Проверьте реальный объем данных, потому что план может измениться во времени.В реальной жизни (если это достаточно быстро) я всегда буду искать второе решение, потому что оно более читабельно и легко поддерживается.

0 голосов
/ 02 сентября 2010

Одна из причин, по которой ваш второй запрос лучше, заключается в том, что вы не используете подстановочный знак
*.
пояснение для grok

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...