हमें अपने SQL Server 2008 R2 पर हर रात कुछ रिपोर्टिंग करने की आवश्यकता है। रिपोर्ट की गणना में कई घंटे लगते हैं। समय को छोटा करने के लिए हम एक तालिका को प्राथमिकता देते हैं। यह तालिका JOINining 12 के आधार पर बनाई गई है जो काफी बड़ी (दसियों मिलें पंक्ति) टेबल हैं।
इस एकत्रीकरण तालिका की गणना कुछ दिनों पहले cca 4 घंटे तक हुई थी। हमारे डीबीए ने इस बड़े विभाजन को 3 छोटे जोड़ (प्रत्येक 4 तालिकाओं में शामिल) में विभाजित किया। अस्थायी परिणाम को हर बार एक अस्थायी तालिका में सहेजा जाता है, जिसका उपयोग अगली जॉइन में किया जाता है।
डीबीए वृद्धि का परिणाम यह है, कि एकत्रीकरण तालिका की गणना 15 मिनट में की जाती है। मैं सोच रहा था कि यह कैसे संभव है। डीबीए ने मुझे बताया कि ऐसा इसलिए है क्योंकि सर्वर द्वारा प्रोसेस की जाने वाली डेटा की संख्या छोटी है। दूसरे शब्दों में, कि बड़े मूल में शामिल होने के लिए सर्वर को छोटे से छोटे जोड़ की तुलना में अधिक डेटा के साथ काम करना पड़ता है। हालाँकि, मुझे लगता है कि ऑप्टिमाइज़र मूल बड़ी जॉइन के साथ इसे कुशलतापूर्वक करने का ध्यान रखेगा, जॉइन्ट्स को खुद से विभाजित करेगा और अगले जॉइन करने के लिए आवश्यक कॉलम की संख्या को भेजेगा।
दूसरी बात यह है कि उसने अस्थायी तालिकाओं में से एक पर एक सूचकांक बनाया है। हालांकि, एक बार फिर मुझे लगता है कि यदि आवश्यक हो तो ऑप्टिमाइज़र उपयुक्त हैश तालिकाओं का निर्माण करेगा और पूरी तरह से बेहतर गणना का अनुकूलन करेगा।
मैंने हमारे डीबीए के साथ इस बारे में बात की, लेकिन वह खुद अनिश्चित था कि प्रसंस्करण समय में क्या सुधार हुआ। उन्होंने सिर्फ उल्लेख किया, कि वे सर्वर को दोष नहीं देंगे क्योंकि यह इस तरह के बड़े डेटा की गणना करने के लिए भारी हो सकता है और यह संभव है कि ऑप्टिमाइज़र के पास सर्वश्रेष्ठ निष्पादन योजना की भविष्यवाणी करने के लिए कठिन समय हो ...। यह मैं समझता हूं, लेकिन मैं अधिक सटीक उत्तर देना चाहूंगा जैसे कि क्यों।
तो, प्रश्न हैं:
संभवतः बड़े सुधार का कारण क्या हो सकता है?
क्या यह एक मानक प्रक्रिया है कि बड़े जॉइन को छोटे में विभाजित किया जाए?
क्या डेटा की मात्रा है जो सर्वर कई छोटे जुड़ने के मामले में वास्तव में छोटा है?
यहाँ मूल प्रश्न है:
Insert Into FinalResult_Base
SELECT
TC.TestCampaignContainerId,
TC.CategoryId As TestCampaignCategoryId,
TC.Grade,
TC.TestCampaignId,
T.TestSetId
,TL.TestId
,TSK.CategoryId
,TT.[TestletId]
,TL.SectionNo
,TL.Difficulty
,TestletName = Char(65+TL.SectionNo) + CONVERT(varchar(4),6 - TL.Difficulty)
,TQ.[QuestionId]
,TS.StudentId
,TS.ClassId
,RA.SubjectId
,TQ.[QuestionPoints]
,GoodAnswer = Case When TQ.[QuestionPoints] Is null Then 0
When TQ.[QuestionPoints] > 0 Then 1
Else 0 End
,WrongAnswer = Case When TQ.[QuestionPoints] = 0 Then 1
When TQ.[QuestionPoints] Is null Then 1
Else 0 End
,NoAnswer = Case When TQ.[QuestionPoints] Is null Then 1 Else 0 End
,TS.Redizo
,TT.ViewCount
,TT.SpentTime
,TQ.[Position]
,RA.SpecialNeeds
,[Version] = 1
,TestAdaptationId = TA.Id
,TaskId = TSK.TaskId
,TaskPosition = TT.Position
,QuestionRate = Q.Rate
,TestQuestionId = TQ.Guid
,AnswerType = TT.TestletAnswerTypeId
FROM
[TestQuestion] TQ WITH (NOLOCK)
Join [TestTask] TT WITH (NOLOCK) On TT.Guid = TQ.TestTaskId
Join [Question] Q WITH (NOLOCK) On TQ.QuestionId = Q.QuestionId
Join [Testlet] TL WITH (NOLOCK) On TT.TestletId = TL.Guid
Join [Test] T WITH (NOLOCK) On TL.TestId = T.Guid
Join [TestSet] TS WITH (NOLOCK) On T.TestSetId = TS.Guid
Join [RoleAssignment] RA WITH (NOLOCK) On TS.StudentId = RA.PersonId And RA.RoleId = 1
Join [Task] TSK WITH (NOLOCK) On TSK.TaskId = TT.TaskId
Join [Category] C WITH (NOLOCK) On C.CategoryId = TSK.CategoryId
Join [TimeWindow] TW WITH (NOLOCK) On TW.Id = TS.TimeWindowId
Join [TestAdaptation] TA WITH (NOLOCK) On TA.Id = TW.TestAdaptationId
Join [TestCampaign] TC WITH (NOLOCK) On TC.TestCampaignId = TA.TestCampaignId
WHERE
T.TestTypeId = 1 -- eliminuji ankety
And t.ProcessedOn is not null -- ne vsechny, jen dokoncene
And TL.ShownOn is not null
And TS.Redizo not in (999999999, 111111119)
END;
डीबीए महान कार्य के बाद नए स्प्लिट्स जुड़ते हैं:
SELECT
TC.TestCampaignContainerId,
TC.CategoryId As TestCampaignCategoryId,
TC.Grade,
TC.TestCampaignId,
T.TestSetId
,TL.TestId
,TL.SectionNo
,TL.Difficulty
,TestletName = Char(65+TL.SectionNo) + CONVERT(varchar(4),6 - TL.Difficulty) -- prevod na A5, B4, B5 ...
,TS.StudentId
,TS.ClassId
,TS.Redizo
,[Version] = 1 -- ?
,TestAdaptationId = TA.Id
,TL.Guid AS TLGuid
,TS.TimeWindowId
INTO
[#FinalResult_Base_1]
FROM
[TestSet] [TS] WITH (NOLOCK)
JOIN [Test] [T] WITH (NOLOCK)
ON [T].[TestSetId] = [TS].[Guid] AND [TS].[Redizo] NOT IN (999999999, 111111119) AND [T].[TestTypeId] = 1 AND [T].[ProcessedOn] IS NOT NULL
JOIN [Testlet] [TL] WITH (NOLOCK)
ON [TL].[TestId] = [T].[Guid] AND [TL].[ShownOn] IS NOT NULL
JOIN [TimeWindow] [TW] WITH (NOLOCK)
ON [TW].[Id] = [TS].[TimeWindowId] AND [TW].[IsActive] = 1
JOIN [TestAdaptation] [TA] WITH (NOLOCK)
ON [TA].[Id] = [TW].[TestAdaptationId] AND [TA].[IsActive] = 1
JOIN [TestCampaign] [TC] WITH (NOLOCK)
ON [TC].[TestCampaignId] = [TA].[TestCampaignId] AND [TC].[IsActive] = 1
JOIN [TestCampaignContainer] [TCC] WITH (NOLOCK)
ON [TCC].[TestCampaignContainerId] = [TC].[TestCampaignContainerId] AND [TCC].[IsActive] = 1
;
SELECT
FR1.TestCampaignContainerId,
FR1.TestCampaignCategoryId,
FR1.Grade,
FR1.TestCampaignId,
FR1.TestSetId
,FR1.TestId
,TSK.CategoryId AS [TaskCategoryId]
,TT.[TestletId]
,FR1.SectionNo
,FR1.Difficulty
,TestletName = Char(65+FR1.SectionNo) + CONVERT(varchar(4),6 - FR1.Difficulty) -- prevod na A5, B4, B5 ...
,FR1.StudentId
,FR1.ClassId
,FR1.Redizo
,TT.ViewCount
,TT.SpentTime
,[Version] = 1 -- ?
,FR1.TestAdaptationId
,TaskId = TSK.TaskId
,TaskPosition = TT.Position
,AnswerType = TT.TestletAnswerTypeId
,TT.Guid AS TTGuid
INTO
[#FinalResult_Base_2]
FROM
#FinalResult_Base_1 FR1
JOIN [TestTask] [TT] WITH (NOLOCK)
ON [TT].[TestletId] = [FR1].[TLGuid]
JOIN [Task] [TSK] WITH (NOLOCK)
ON [TSK].[TaskId] = [TT].[TaskId] AND [TSK].[IsActive] = 1
JOIN [Category] [C] WITH (NOLOCK)
ON [C].[CategoryId] = [TSK].[CategoryId]AND [C].[IsActive] = 1
;
DROP TABLE [#FinalResult_Base_1]
CREATE NONCLUSTERED INDEX [#IX_FR_Student_Class]
ON [dbo].[#FinalResult_Base_2] ([StudentId],[ClassId])
INCLUDE ([TTGuid])
SELECT
FR2.TestCampaignContainerId,
FR2.TestCampaignCategoryId,
FR2.Grade,
FR2.TestCampaignId,
FR2.TestSetId
,FR2.TestId
,FR2.[TaskCategoryId]
,FR2.[TestletId]
,FR2.SectionNo
,FR2.Difficulty
,FR2.TestletName
,TQ.[QuestionId]
,FR2.StudentId
,FR2.ClassId
,RA.SubjectId
,TQ.[QuestionPoints] -- 1+ good, 0 wrong, null no answer
,GoodAnswer = Case When TQ.[QuestionPoints] Is null Then 0
When TQ.[QuestionPoints] > 0 Then 1 -- cookie
Else 0 End
,WrongAnswer = Case When TQ.[QuestionPoints] = 0 Then 1
When TQ.[QuestionPoints] Is null Then 1
Else 0 End
,NoAnswer = Case When TQ.[QuestionPoints] Is null Then 1 Else 0 End
,FR2.Redizo
,FR2.ViewCount
,FR2.SpentTime
,TQ.[Position] AS [QuestionPosition]
,RA.SpecialNeeds -- identifikace SVP
,[Version] = 1 -- ?
,FR2.TestAdaptationId
,FR2.TaskId
,FR2.TaskPosition
,QuestionRate = Q.Rate
,TestQuestionId = TQ.Guid
,FR2.AnswerType
INTO
[#FinalResult_Base]
FROM
[#FinalResult_Base_2] FR2
JOIN [TestQuestion] [TQ] WITH (NOLOCK)
ON [TQ].[TestTaskId] = [FR2].[TTGuid]
JOIN [Question] [Q] WITH (NOLOCK)
ON [Q].[QuestionId] = [TQ].[QuestionId] AND [Q].[IsActive] = 1
JOIN [RoleAssignment] [RA] WITH (NOLOCK)
ON [RA].[PersonId] = [FR2].[StudentId]
AND [RA].[ClassId] = [FR2].[ClassId] AND [RA].[IsActive] = 1 AND [RA].[RoleId] = 1
drop table #FinalResult_Base_2;
truncate table [dbo].[FinalResult_Base];
insert into [dbo].[FinalResult_Base] select * from #FinalResult_Base;
drop table #FinalResult_Base;
READCOMMITTED
? मैंने पहले कभी ROWCOMMITTED नहीं देखा है।