Sql 如何提高此查询的性能?

Sql 如何提高此查询的性能?,sql,sql-server,rdbms,Sql,Sql Server,Rdbms,关于这个问题,我能够得到我想要的报告 有人告诉我,在现实世界中,学生表将有3000万条记录。我有学生ID的索引,日期。是否有改进性能的建议,或者是否有更好的方法来构建报告 现在我有以下问题 ;with cte as ( select id, studentid, date, '#'+subject+';'+grade+';'+convert(varchar(10), date, 101) report from student ) -- insert into

关于这个问题,我能够得到我想要的报告

有人告诉我,在现实世界中,学生表将有3000万条记录。我有学生ID的索引,日期。是否有改进性能的建议,或者是否有更好的方法来构建报告

现在我有以下问题

;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;

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

不要使用cte,因为它们通常不会处理具有大内存的查询,至少在我的经验中是这样。取而代之的是,将cte数据放在一个真实的表中,可以使用物化/索引视图,也可以使用一个工作表(可能是一个大的临时表)。然后执行cte后的第二个选择,将数据合并到一个有序列表中

对您的问题的评论数量表明您有一个或多个大问题。您正在将高瘦数据(如整数、datetime2类型)转换为字符串中的有序列表。试着用可用的最小数据格式存储数据,然后再将其转换成字符串,直到以后,或者永远不要。或者,认真考虑创建一个XML数据字段来替换“report”字段

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

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;

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

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

不要使用cte,因为它们通常不会处理具有大内存的查询,至少在我的经验中是这样。取而代之的是,将cte数据放在一个真实的表中,可以使用物化/索引视图,也可以使用一个工作表(可能是一个大的临时表)。然后执行cte后的第二个选择,将数据合并到一个有序列表中

对您的问题的评论数量表明您有一个或多个大问题。您正在将高瘦数据(如整数、datetime2类型)转换为字符串中的有序列表。试着用可用的最小数据格式存储数据,然后再将其转换成字符串,直到以后,或者永远不要。或者,认真考虑创建一个XML数据字段来替换“report”字段

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

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;

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

执行计划在哪里?;将cte作为选择id、学生id、日期+科目+';'+等级+';'+convertvarchar10,date,101来自学生的报告-插入studentreport选择不同的studentid,填充选择castt2.report作为来自cte t2的varchar50,其中c.studentid=t2.studentid按t2排序。XML路径1,0的日期描述作为来自cte c的报告;日期范围意味着处理的记录更少。这将提高性能。这可能也会使您的报告更具相关性。@Think不必查询3000万行,您是否可以包含where date>='2012-01-01'和date@Think get SQL Sentry->它具有匿名功能。使用它,您将有一个清晰的计划来显示,并且对计划中的问题有不同的看法;。执行计划在哪里?;将cte作为选择id、学生id、日期+科目+';'+等级+';'+convertvarchar10,date,101来自学生的报告-插入studentreport选择不同的studentid,填充选择castt2.report作为来自cte t2的varchar50,其中c.studentid=t2.studentid按t2排序。XML路径1,0的日期描述作为来自cte c的报告;日期范围意味着处理的记录更少。这将提高性能。这可能也会使您的报告更具相关性。@Think不必查询3000万行,您是否可以包含where date>='2012-01-01'和date@Think get SQL Sentry->它具有匿名功能。使用它,您将有一个清晰的计划来显示,并且对计划中的问题有不同的看法;。这也是我的想法-CTE可能会减慢这一速度,从而产生一个不需要的额外步骤。非常感谢您的建议。我确实删除并直接编写了查询。虽然时间更长,但比CTE好。这也是我的想法——CTE可能会减慢cre的速度
这是一个不需要的额外步骤。非常感谢您的建议。我确实删除并直接编写了查询。虽然时间更长,但比CTE好。