ভিউ থেকে নির্বাচন করুন 4 মিনিট সময় নেয়


11

আমি এমন একটি ইস্যুতে ছুটে যাচ্ছি যেখানে আমি যখন একটি ভিউয়ের বিরুদ্ধে কোয়েরি চালাই তবে এটি 4+ মিনিট সময় নেয়। যাইহোক, আমি যখন ক্যোয়ারির সাহস চালাই তখন এটি 1 সেকেন্ডের মতো শেষ হয়।

কেবলমাত্র যে বিষয়টি সম্পর্কে আমি নিশ্চিত নই সেগুলি হল যে সারণীগুলি যুক্ত হচ্ছে তা হ'ল উভয়ই টেম্পোরাল টেবিল।

অ্যাডহক ক্যোয়ারী পরিকল্পনা: https://www.brentozar.com/pastetheplan/?id=BykohB2p4

ক্যোয়ারী প্ল্যান দেখুন: https://www.brentozar.com/pastetheplan/?id=SkIfTHh6E

এটি চেষ্টা করার এবং এটি বের করার বিষয়ে কোনও পরামর্শ?

কোড দেখুন:

ALTER VIEW [dbo].[vwDealHistoryPITA]
AS
SELECT ROW_NUMBER() OVER (PARTITION BY cm.CodeMasterID ORDER BY cm.CodeMasterID, cm.LastUpdateDate) AS Deal_HistoryID,
       cm.CodeMasterID,
       cm.ProjectName,
       cm.[Status],
       d.CompanyID,
       d.DealTypeMasterID,
       cm.[Description],
       d.PassiveInd,
       d.ApproxTPGOwnership,
       d.NumberBoardSeats,
       d.FollowonInvestmentInd,
       d.SocialImpactInd,
       d.EquityInd,
       d.DebtInd,
       d.RealEstateInd,
       d.TargetPctgReturn,
       d.ApproxTotalDealSize,
       cm.CurrencyCode,
       d.ConflictCheck,
       cm.CreatedDate,
       cm.CreatedBy,
       cm.LastUpdateDate,
       cm.LastUpdateBy,
       d.ExpensesExceedThresholdDate,
       d.CurrentTPGCheckSize,
       d.PreferredEquityInd,
       d.ConvertibleDebtInd,
       d.OtherRealAssetsInd,
       d.InitialTPGCheckSize,
       d.DirectLendingInd,
       cm.NameApproved,
       cm.FolderID,
       cm.CodaProcessedDateTime,
       cm.DeadDate,
       d.SectorMasterID,
       d.DTODataCompleteDate,
       cm.ValidFrom AS CodeMasterValidFrom,
       cm.ValidTo   AS CodeMasterValidTo,
       d.validFrom  AS DealValidFrom,
       d.validTo    AS DealValidTo
FROM dbo.CodeMaster FOR SYSTEM_TIME ALL cm 
INNER JOIN dbo.Deal FOR SYSTEM_TIME ALL d ON cm.CodeMasterID = d.CodeMasterID;
GO

দ্বারা পার্টিশন যুক্ত এবং অ্যাডক কোয়েরিতে অনুরূপ ফলাফল পান।

উত্তর:


18

প্রধান পারফরম্যান্স পার্থক্য

এখানে মূল পার্থক্য হ'ল আরও ভাল পারফরম্যান্স ক্যোয়ারী CodeMasterIDসমস্ত 4 টেবিলগুলিতে সিক প্রিকিকেটটিকে নীচে চাপিয়ে দিচ্ছে (২ টি টেম্পোরাল টেবিল (প্রকৃত ও ইতিহাস)) যেখানে ভিউতে নির্বাচন করা শেষ পর্যন্ত (ফিল্টার অপারেটর) এটি না করে বলে মনে হচ্ছে ।

টিএল ডিআর;

সমস্যাটি প্যারামিটারগুলির কারণে নির্দিষ্ট কিছু ক্ষেত্রে যেমন উইন্ডো ফাংশনগুলিতে চাপ দিচ্ছে না। সবচেয়ে সহজ সমাধানটি OPTION(RECOMPILE)ভিউ কলটিতে যুক্ত করা হচ্ছে যাতে রানটাইমের সময় অপটিমাইজারটি 'দেখুন' করতে পারে যদি কোনও সম্ভাবনা থাকে। যদি প্রতিটি ক্যোয়ারী কলের জন্য এক্সিকিউশন প্ল্যানটি পুনরায় কম্পাইল করা খুব ব্যয়বহুল হয় তবে একটি ইনলাইন টেবিলের মূল্যবান ফাংশন যা প্রত্যাশা করে যে কোনও প্যারামিটার সমাধান হতে পারে। একটা চমৎকার ব্লগপোস্টটিকে দ্বারা পল হোয়াইট এই। আপনার নির্দিষ্ট সমস্যাটি সন্ধান এবং সমাধান করার আরও বিশদ উপায়ের জন্য, পড়া চালিয়ে যান।


আরও ভাল পারফরম্যান্স ক্যোয়ারী

কোডমাস্টার টেবিল

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

ডিল টেবিল

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

আমি সন্ধানের গন্ধটি সকালে অনুমান করি love


বড় খারাপ প্রশ্ন

কোডমাস্টার টেবিল

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

এটি একটি প্রাক্কলিত একমাত্র জোন

ডিল টেবিল

এখানে চিত্র বর্ণনা লিখুন

তবে অপ্টিমাইজারটি 'চুক্তির শিল্প read "পড়েনি

এখানে চিত্র বর্ণনা লিখুন

... এবং অতীত থেকে শেখা হয় না

যতক্ষণ না সমস্ত ডেটা ফিল্টার অপারেটরে পৌঁছে যায়

এখানে চিত্র বর্ণনা লিখুন


তো, কি দেয়?

এখানে মূল সমস্যাটি অপটিমাইজারটি ভিউটিতে উইন্ডো ফাংশনের কারণে রানটাইমগুলিতে প্যারামিটারগুলি 'না দেখে' এবং ব্যবহার করতে সক্ষম না হওয়ায় SelOnSeqPrj (অনুক্রমের প্রকল্পে নির্বাচন করুন, আরও নীচে এই পোস্টে রেফারেন্সের জন্য)

আমি পরীক্ষার নমুনা দিয়ে এবং একই সাথে SP_EXECUTESQLফলাফলটিকে কলটি প্যারামিটারাইজ করতে ব্যবহার করে একই ফলাফলগুলি প্রতিলিপি করতে সক্ষম হয়েছি । ডিডিএল / ডিএমএলের সংযোজন দেখুন See

উইন্ডো ফাংশন এবং একটি দিয়ে একটি পরীক্ষা দর্শনের বিরুদ্ধে একটি ক্যোয়ারী কার্যকর করা INNER JOIN

SET STATISTICS IO, TIME ON;
EXEC SP_EXECUTESQL
N'SELECT * FROM  dbo.Bad
Where CodeMasterID = @P1',N'@P1 INT',@P1 = 37155;

সিপিইউ সময় এবং s.২ এস সময় অতিবাহিত হয়েছে প্রায় 4.5s এর ফলাফল

 SQL Server Execution Times:
   CPU time = 4595 ms,  elapsed time = 3209 ms.

আমরা যখন মিষ্টি আলিঙ্গন যোগ OPTION(RECOMPILE)

SET STATISTICS IO, TIME ON;
EXEC SP_EXECUTESQL
N'SELECT * FROM  dbo.Bad
Where CodeMasterID = @P1 OPTION(RECOMPILE)',N'@P1 INT',@P1 = 37155; 

সব ঠিক আছে.

 SQL Server Execution Times:
   CPU time = 16 ms,  elapsed time = 98 ms.

কেন

@P1উইন্ডো ফাংশন এবং প্যারামিটারাইজেশনের ফলে ফিল্টার অপারেটরের ফলে টেবিলে প্রিডিকেট প্রয়োগ করতে সক্ষম না হওয়ার পয়েন্টটি এটি আবারও সমর্থন করে

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন

টেম্পোরাল টেবিলগুলির জন্য কেবল একটি ইস্যু নয়

সংযোজন 2 দেখুন

এমনকি টেম্পোরাল টেবিল ব্যবহার না করার পরেও এটি ঘটে: এখানে চিত্র বর্ণনা লিখুন

কোয়েরি লেখার সময় একই ফলাফলটি দেখা যায়:

DECLARE @P1 int = 37155
SELECT * FROM  dbo.Bad2
Where CodeMasterID = @P1;

আবার, অপ্টিমাইজার উইন্ডো ফাংশন প্রয়োগ করার আগে প্রিকিকেটটি নীচে চাপ দিচ্ছে না।

ROW_NUMBER () বাদ দিলে

CREATE VIEW dbo.Bad3
as
SELECT
cm.CodeMasterID,CM.ManagerID,cm.ParentDeptID,d.DealID, d.CodeMasterID as dealcodemaster,d.EvenMoreBlaID
FROM dbo.CodeMaster2  cm 
INNER JOIN dbo.Deal2  d ON cm.CodeMasterID = d.CodeMasterID;

সবকিছু ঠিক আছে

SET STATISTICS IO, TIME ON;
EXEC SP_EXECUTESQL
N'SELECT * FROM  dbo.Bad3
Where CodeMasterID = @P1',N'@P1 INT',@P1 = 37155


 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 33 ms.

তাহলে আমাদের সব ছেড়ে যায় কোথায়?

ROW_NUMBER()সামনে ফিল্টার খারাপ প্রশ্নের উপর প্রয়োগ করা হয় গণনা করা হয়।

এবং এই সমস্ত উইন্ডো ফাংশন এবং ভিউগুলিতে পল হোয়াইট দ্বারা 2013 থেকে আমাদের এই ব্লগপোস্টে নিয়ে যায় ।

আমাদের উদাহরণের জন্য গুরুত্বপূর্ণ অংশগুলির একটি হ'ল এই বিবৃতি:

দুর্ভাগ্যক্রমে, SelOnSeqPrj সরলীকরণের নিয়ম কেবল তখনই কাজ করে যখন শিকারী একটি ধ্রুবকের সাথে তুলনা করে। সেই কারণে, নিম্নলিখিত কোয়েরিটি এসকিউএল সার্ভার ২০০৮ এবং তারপরে উপ-অনুকূল পরিকল্পনা তৈরি করে:

DECLARE @ProductID INT = 878;

SELECT
    mrt.ProductID,
    mrt.TransactionID,
    mrt.ReferenceOrderID,
    mrt.TransactionDate,
    mrt.Quantity
FROM dbo.MostRecentTransactionsPerProduct AS mrt 
WHERE
    mrt.ProductID = @ProductID;

এখানে চিত্র বর্ণনা লিখুন

এই অংশটি প্যারামিটারটি নিজেরাই ঘোষণা করার সময় / ভিউটিতে ব্যবহার SP_EXECUTESQLকরার সময় আমরা যা দেখেছি তার সাথে মিলে যায় ।


আসল সমাধান

1: বিকল্প (প্রস্তাবনা)

আমরা জানি যে OPTION(RECOMPILE)রানটাইমের সময় মানটি 'দেখার' সম্ভাবনা। প্রতিটি ক্যোয়ারী কলের জন্য এক্সিকিউশন প্ল্যানটি সংশোধন করার সময় খুব ব্যয়বহুল, অন্য সমাধান রয়েছে।

2: একটি পরামিতি সহ ইনলাইন টেবিলের মূল্যবান ফাংশন

CREATE FUNCTION dbo.BlaBla
(
    @P1 INT
)  
RETURNS TABLE
WITH SCHEMABINDING AS
RETURN
    (
     SELECT 
     ROW_NUMBER() OVER (PARTITION BY cm.CodeMasterID ORDER BY cm.CodeMasterID) AS Deal_HistoryID,
     cm.CodeMasterID,CM.ManagerID,
     cm.ParentDeptID,d.DealID,
     d.CodeMasterID as dealcodemaster,
     d.EvenMoreBlaID
    FROM dbo.CodeMaster2  cm 
    INNER JOIN dbo.Deal2  d ON cm.CodeMasterID = d.CodeMasterID
    Where cm.CodeMasterID = @P1
    ) 
EXEC SP_EXECUTESQL
N'SELECT * FROM  dbo.BlaBLa(@P1)',N'@P1 INT',@P1 = 37155

প্রত্যাশিত সন্ধানের ফলাফলগুলি পূর্বাভাস দেয়

     SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 0 ms.

আমার পরীক্ষায় প্রায় 9 টি যৌক্তিক পাঠ রয়েছে

3: ভিউ ব্যবহার না করে ক্যোয়ারী লেখা।

অন্য 'সমাধান' কোনও ভিউ ব্যবহার না করেই ক্যোয়ারীটি সম্পূর্ণ লিখতে পারে।

4: ROW_NUMBER()ফাংশনটি ভিউতে রাখছেন না , পরিবর্তে দর্শনটিতে এটি কল করে।

এর উদাহরণ হ'ল:

CREATE VIEW dbo.Bad2
as
SELECT 
cm.CodeMasterID,CM.ManagerID,cm.ParentDeptID,d.DealID, d.CodeMasterID as dealcodemaster,d.EvenMoreBlaID
FROM dbo.CodeMaster2  cm 
INNER JOIN dbo.Deal2  d ON cm.CodeMasterID = d.CodeMasterID;

GO
SET STATISTICS IO, TIME ON;
EXEC SP_EXECUTESQL
N'SELECT ROW_NUMBER() OVER (PARTITION BY CodeMasterID ORDER BY CodeMasterID) AS Deal_HistoryID,* FROM  dbo.Bad2
Where CodeMasterID = @P1',N'@P1 INT',@P1 = 37155;

এই সমস্যাটির চারপাশে অন্যান্য সৃজনশীল উপায় থাকতে হবে, গুরুত্বপূর্ণ অংশটি এটি কী কারণ তা জেনে রাখা।


পরিসংখ্যান # 1

CREATE TABLE dbo.Codemaster   
(    
     CodeMasterID int NOT NULL PRIMARY KEY CLUSTERED  
   , ManagerID INT  NULL  
   , ParentDeptID int NULL  
   , SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL  
   , SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL  
   , PERIOD FOR SYSTEM_TIME (SysStartTime,SysEndTime)     
)    
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Codemaster_History))   
;  

CREATE TABLE dbo.Deal   
(    
     DealID int NOT NULL PRIMARY KEY CLUSTERED  
   , CodeMasterID INT  NULL  
   , EvenMoreBlaID int NULL  
   , SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL  
   , SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL  
   , PERIOD FOR SYSTEM_TIME (SysStartTime,SysEndTime)     
)    
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Deal_History))   
;  

INSERT INTO dbo.Codemaster(CodeMasterID,ManagerID,ParentDeptID)
SELECT TOP(1000000) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum1,
                    ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum2,
                    ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum3
FROM MASTER..spt_values as spt1
CROSS JOIN MASTER..spt_values as spt2;


INSERT INTO dbo.Deal(DealID,CodeMasterID,EvenMoreBlaID)
SELECT TOP(1000000) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum1,
                    ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum2,
                    ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum3
FROM MASTER..spt_values as spt1
CROSS JOIN MASTER..spt_values as spt2;

CREATE INDEX IX_CodeMasterID
ON dbo.Deal(CodeMasterId);
CREATE INDEX IX_CodeMasterID
ON dbo.Deal_History(CodeMasterId);

CREATE INDEX IX_CodeMasterID
ON dbo.Codemaster(CodeMasterId);
CREATE INDEX IX_CodeMasterID
ON dbo.Codemaster_History(CodeMasterId);


SELECT ROW_NUMBER() OVER (PARTITION BY cm.CodeMasterID ORDER BY cm.CodeMasterID, cm.SysStartTime) AS Deal_HistoryID,
cm.*, d.* 
FROM dbo.CodeMaster FOR SYSTEM_TIME ALL cm 
INNER JOIN dbo.Deal FOR SYSTEM_TIME ALL d ON cm.CodeMasterID = d.CodeMasterID
Where cm.CodeMasterID = 37155;

-- Guud
GO
CREATE VIEW dbo.Bad
as
SELECT ROW_NUMBER() OVER (PARTITION BY cm.CodeMasterID ORDER BY cm.CodeMasterID, cm.SysStartTime) AS Deal_HistoryID,
cm.CodeMasterID,CM.ManagerID,cm.ParentDeptID,d.DealID, d.CodeMasterID as dealcodemaster,d.EvenMoreBlaID
FROM dbo.CodeMaster FOR SYSTEM_TIME ALL cm 
INNER JOIN dbo.Deal FOR SYSTEM_TIME ALL d ON cm.CodeMasterID = d.CodeMasterID

GO
EXEC SP_EXECUTESQL
N'SELECT * FROM  dbo.Bad
Where CodeMasterID = @P1',N'@P1 INT',@P1 = 37155

-- Very bad shame on you

পরিসংখ্যান # 2

CREATE TABLE dbo.Codemaster2
(    
     CodeMasterID int NOT NULL PRIMARY KEY CLUSTERED  
   , ManagerID INT  NULL  
   , ParentDeptID int NULL  

);  

CREATE TABLE dbo.Deal2
(    
     DealID int NOT NULL PRIMARY KEY CLUSTERED  
   , CodeMasterID INT  NULL  
   , EvenMoreBlaID int NULL    
);  

INSERT INTO dbo.Codemaster2(CodeMasterID,ManagerID,ParentDeptID)
SELECT TOP(1000000) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum1,
                    ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum2,
                    ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum3
FROM MASTER..spt_values as spt1
CROSS JOIN MASTER..spt_values as spt2;


INSERT INTO dbo.Deal2(DealID,CodeMasterID,EvenMoreBlaID)
SELECT TOP(1000000) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum1,
                    ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum2,
                    ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) as rownum3
FROM MASTER..spt_values as spt1
CROSS JOIN MASTER..spt_values as spt2;

CREATE INDEX IX_CodeMasterID
ON dbo.Deal2(CodeMasterId);
CREATE INDEX IX_CodeMasterID
ON dbo.Codemaster2(CodeMasterId);


SELECT ROW_NUMBER() OVER (PARTITION BY cm.CodeMasterID ORDER BY cm.CodeMasterId) AS Deal_HistoryID,
cm.*, d.* 
FROM dbo.CodeMaster2 cm 
INNER JOIN dbo.Deal2 d ON cm.CodeMasterID = d.CodeMasterID
Where cm.CodeMasterID = 37155;

-- Guud
GO
CREATE VIEW dbo.Bad2
as
SELECT ROW_NUMBER() OVER (PARTITION BY cm.CodeMasterID ORDER BY cm.CodeMasterID) AS Deal_HistoryID,
cm.CodeMasterID,CM.ManagerID,cm.ParentDeptID,d.DealID, d.CodeMasterID as dealcodemaster,d.EvenMoreBlaID
FROM dbo.CodeMaster2  cm 
INNER JOIN dbo.Deal2  d ON cm.CodeMasterID = d.CodeMasterID

GO
SET STATISTICS IO, TIME ON;
EXEC SP_EXECUTESQL
N'SELECT * FROM  dbo.Bad2
Where CodeMasterID = @P1',N'@P1 INT',@P1 = 37155
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.