如何提高此查询的性能?

时间:2013-05-07 18:22:04

标签: sql sql-server rdbms

参考SQL Query how to summarize students record by date?我能够得到我想要的报告。

在现实世界中,我被告知学生表将有3000万条记录。我有索引(StudentID,日期)。有任何改进性能的建议,还是有更好的方法来构建报告?

现在我有以下查询

;with cte as
(
  select id, 
    studentid,
    date,
    '#'+subject+';'+grade+';'+convert(varchar(10), date, 101) report
  from student
) 
-- insert into studentreport
select distinct 
  studentid,
  STUFF(
         (SELECT cast(t2.report as varchar(50))
          FROM cte t2
          where c.StudentId = t2.StudentId
          order by t2.date desc
          FOR XML PATH (''))
          , 1, 0, '')  AS report
from cte c;

1 个答案:

答案 0 :(得分:1)

如果没有看到执行计划,就不可能编写优化的SQL语句,因此我会提出建议。

不要使用cte,因为他们经常不处理大内存需要的查询(至少,根据我的经验)。相反,将cte数据放在实际表中,使用物化/索引视图或工作表(可能是大型临时表)。然后执行第二个选择(在cte之后)以将数据组合在有序列表中。

您的问题的评论数量表明您遇到了大问题(或问题)。您将高和瘦的数据(将整数,datetime2类型)转换为字符串中的有序列表。试着考虑以可用的最小数据格式存储并在之后(或从不)操作字符串。或者,请认真考虑创建XML数据字段以替换“报告”字段。

如果你可以使它工作,这就是我要做的(包括没有索引的测试用例)。您的里程可能会有所不同,但请尝试一下:

create table #student (id int not null, studentid int not null, date datetime not null, subject varchar(40), grade varchar(40))

insert into #student (id,studentid,date,subject,grade)
select 1, 1, getdate(), 'history', 'A-' union all
select 2, 1, dateadd(d,1,getdate()), 'computer science', 'b' union all
select 3, 1, dateadd(d,2,getdate()), 'art', 'q' union all
--
select 1, 2, getdate() , 'something', 'F' union all
select 2, 2, dateadd(d,1,getdate()), 'genetics', 'e' union all
select 3, 2, dateadd(d,2,getdate()), 'art', 'D+' union all
--
select 1, 3, getdate() , 'memory loss', 'A-' union all
select 2, 3, dateadd(d,1,getdate()), 'creative writing', 'A-' union all
select 3, 3, dateadd(d,2,getdate()), 'history of asia 101', 'A-'

go

select      studentid as studentid
            ,(select s2.date as '@date', s2.subject as '@subject', s2.grade as '@grade' 
            from #student s2 where s1.studentid = s2.studentid for xml path('report'), type) as 'reports'
from        (select distinct studentid from #student) s1;

我不知道如何使输出清晰,但结果集是2个字段。字段1是整数,字段2是XML,每个报告一个节点。这仍然不如发送结果集那么理想,但每个studentid至少有一个结果。