2013-05-07 2 views
1

SQL Query how to summarize students record by date?과 관련하여 내가 원하는 보고서를 얻을 수있었습니다.이 쿼리의 성능을 향상시키는 방법은 무엇입니까?

나는 실제 세계에서 학생들의 테이블에 30 만개의 레코드가 있다고 들었다. 나는 인덱스를 가지고있다 (StudentID, Date). 실적을 개선하기위한 제안이나 보고서를 작성하는 더 좋은 방법이 있습니까?

가 지금 내가 실행 계획을보고하지 않고 다음 쿼리

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

실행 계획은 어디에 있습니까? –

+0

;와 CTE ( 선택 아이디, studentid, 날짜, '#'+ 주제 + ','+ 등급 + ','+ 변환 (VARCHAR (10), 날짜, 101) 학생 에서 를보고) 등 - 뚜렷한 studentid, STUFF를 (선택 studentreport 삽입 (여기서 c.StudentId = t2.StudentId 주문 t2.date 내림차순으로 CTE T2 FROM VARCHAR (50)) 등 캐스트 (t2.report를 선택 XML PATH ('')) , 1, 0, '') AS 보고서 에서 cte c; – Think

+3

날짜 범위는 처리되는 레코드의 수가 적음을 의미합니다. 그러면 성능이 향상됩니다. 보고서가 더 관련성이 높을 수도 있습니다. –

답변

1

을 가지고, 내가 대신 제안을 할 것입니다 수 있도록 최적화 된 SQL 문을 작성하는 정말 수 없습니다.

대용량 메모리가있는 쿼리를 처리하지 않으므로 cte를 사용하지 마십시오. (적어도 내 경험에서는) 잘 작동해야합니다. 대신 materialized/indexed 뷰 또는 작업 테이블 (아마도 큰 임시 테이블)을 사용하여 실제 테이블에 cte 데이터를 배치하십시오. 그런 다음 두 번째 선택 (cte 뒤에)을 실행하여 데이터를 정렬 된 목록에 결합하십시오.

질문에 대한 의견 수는 귀하에게 큰 문제 (또는 문제)가 있음을 나타냅니다. 키가 크고 마른 체형의 데이터 (정수, datetime2 형)를 문자열 내에서 정렬 된 목록으로 변환합니다. 대신 가장 작은 데이터 형식으로 저장하고 문자열을 조작 할 때까지 (또는 전혀 사용하지 않을 때까지) 생각해보십시오. 또는 'report'필드를 대체 할 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입니다. 결과 세트를 보내는 것만 큼 이상한 것은 아니지만 학생 ID 당 적어도 하나의 결과입니다.

+0

이것은 내 생각이기도합니다. CTE는 아마도 이것을 필요로하지 않는 추가 단계를 만드는 속도를 늦출 것입니다. – Jasmine

+0

제안 해 주셔서 대단히 감사합니다. 나는 직접 쿼리를 제거하고 썼다. 여전히 CTE보다 시간이 더 오래 걸리지 만 더 좋습니다. – Think

관련 문제