哪个查询效果好?

时间:2010-09-02 17:42:55

标签: sql sql-server tsql sql-server-2008

我想知道下面两个查询中的哪一个更快: -

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;

编辑: -

第一次查询的查询估算: - http://img28.imageshack.us/img28/166/1stpicd.jpg

第二次查询的查询估算: - http://img245.imageshack.us/img245/5064/2ndpic.jpg

提前致谢:)

7 个答案:

答案 0 :(得分:4)

您可以同时运行它们并使用execution plan来比较它们。

答案 1 :(得分:3)

在审核执行计划后,第一个查询更有效 两者都在tblStudentMarks上进行了表扫描,但第一个查询的百分比与第二个查询相比要低得多。 The SORT isn't ideal, but being that the table scan is in both - 通过添加索引可能更容易处理。通过查看索引可以改进SORT和表扫描......

答案 2 :(得分:2)

取决于您的数据和索引。 通常,SQL Server被认为在优化连接方面比在子查询方面更好,并且因为它也更具可读性(因此更易于维护并且不太可能导致错误),我现在选择2(加入),看看是否你遇到了任何表现障碍。如果这是速度关键查询,我会尝试两者并比较结果。确保使用实际数据进行测试。

答案 3 :(得分:1)

您的示例执行计划似乎有点不切实际。在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,则两个查询计划都会显示完全相同

答案 4 :(得分:0)

您的第二个查询更好的一个原因是因为您没有使用*外卡。
explaination to grok

答案 5 :(得分:0)

要加快速度,请勿使用Select *。也可以尝试左连接加入(仅当产生相同的结果时)
选择生产服务器上更快的那个(取决于数据量,索引碎片和索引选择性,查询优化器可以选择与测试服务器相比的不同生产计划)。测试时不要忘记在运行之间清空缓存。测试实际数据量,因为计划可以及时改变 在现实生活中(如果足够快),我将永远为第二个解决方案,因为它更具可读性和可维护性。

答案 6 :(得分:0)

我知道这有点极端,但我有一个类似的查询,我对一些非常大的表运行。假设你在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;