В اهو مضمون ڪجهه اصلاح جا طريقا سمجهيا ويا LINQ سوال.
هتي اسان ڪجهه وڌيڪ طريقا پيش ڪندا آهيون ڪوڊ جي اصلاح سان لاڳاپيل LINQ سوال.
اهو معلوم آهي ته لنڪ(Language-Integrated Query) ڊيٽا ماخذ جي سوال ڪرڻ لاءِ هڪ سادي ۽ آسان ٻولي آهي.
А LINQ کان SQL ڊي بي ايم ايس ۾ ڊيٽا تائين رسائي جي ٽيڪنالاجي آهي. هي ڊيٽا سان ڪم ڪرڻ لاءِ هڪ طاقتور اوزار آهي، جتي سوالن کي هڪ بياني ٻولي ذريعي ٺاهيو ويندو آهي، جنهن کي پوءِ ان ۾ تبديل ڪيو ويندو. SQL سوال پليٽ فارم ۽ عمل لاء ڊيٽابيس سرور ڏانهن موڪليو ويو. اسان جي صورت ۾، ڊي بي ايم ايس پاران اسان جو مطلب آهي MS SQL سرور.
جڏهن ته، LINQ سوال بهتر طور تي لکندڙن ۾ تبديل نه ڪيا ويا آهن SQL سوال، جنهن کي هڪ تجربيڪار DBA اصلاح جي سڀني نونسن سان لکي سگهي ٿو SQL سوال:
بهترين ڪنيڪشن (JOIN) ۽ نتيجن کي فلٽر ڪرڻ (جڏهن)
ڪنيڪشن ۽ گروپ جي حالتن کي استعمال ڪرڻ ۾ ڪيترائي nuances
حالتن جي بدلي ۾ ڪيترائي تغيرات IN تي وجودَи اندر نه، <> تي وجودَ
عارضي جدولن، CTE، ٽيبل متغير ذريعي نتيجن جي وچولي ڪيشنگ
جملي جو استعمال (OPTION) هدايتون ۽ ٽيبل اشارن سان سان (...)
چونڊ دوران بيڪار ڊيٽا پڙهڻ کان نجات حاصل ڪرڻ جو هڪ وسيلو طور تي ترتيب ڏنل نظارن کي استعمال ڪندي
نتيجن جي مکيه ڪارڪردگي جي رڪاوٽون SQL سوال جڏهن گڏ ڪرڻ LINQ سوال آهن:
ھڪڙي درخواست ۾ پوري ڊيٽا جي چونڊ ميڪانيزم کي گڏ ڪرڻ
ڪوڊ جي هڪجهڙائي واري بلاڪ کي نقل ڪرڻ، جيڪو آخرڪار ڪيترن ئي غير ضروري ڊيٽا پڙهڻ جي ڪري ٿو
گهڻن حصن جي حالتن جا گروپ (منطقي "۽" ۽ "يا") - ۽ и OR، پيچيده حالتن ۾ ملائيندي، حقيقت ڏانهن وٺي وڃي ٿو ته اصلاحي، ضروري شعبن لاءِ مناسب غير ڪلسٽرڊ انڊيڪس هجڻ ڪري، آخرڪار ڪلستر ٿيل انڊيڪس جي خلاف اسڪين ڪرڻ شروع ڪري ٿو (انڊيڪس اسڪين) شرطن جي گروپن طرفان
ذيلي سوالن جو deep nesting پارس ڪرڻ کي تمام ڏکيو بڻائي ٿو SQL بيان ۽ ڊولپرز جي حصي تي سوال جي منصوبي جو تجزيو ۽ DBA
اصلاحي طريقا
هاڻي اچو ته سڌو سنئون اصلاح جي طريقن ڏانهن وڃو.
1) اضافي انڊيڪسنگ
اهو بهترين آهي فلٽرن تي غور ڪرڻ لاءِ مکيه چونڊ جدولن تي، ڇاڪاڻ ته اڪثر ڪري سڄو سوال هڪ يا ٻه مکيه جدولن (ايپليڪيشن-ماڻهن-آپريشنز) جي چوڌاري ٺهيل هوندو آهي ۽ شرطن جي معياري سيٽ سان (IsClosed، منسوخ ٿيل، فعال، اسٽيٽس). اهو ضروري آهي ته سڃاڻپ نموني لاء مناسب انڊيڪس ٺاهي.
هي حل سمجھ ۾ اچي ٿو جڏهن انهن شعبن کي چونڊيو خاص طور تي سوال ڏانهن موٽايل سيٽ کي محدود ڪري ٿو.
مثال طور، اسان وٽ 500000 ايپليڪيشنون آهن. بهرحال، اتي صرف 2000 فعال ايپليڪيشنون آهن. پوء هڪ صحيح چونڊيل انڊيڪس اسان کي بچائيندو انڊيڪس اسڪين هڪ وڏي ٽيبل تي ۽ توهان کي غير ڪلستر ٿيل انڊيڪس ذريعي جلدي ڊيٽا کي چونڊڻ جي اجازت ڏيندو.
انهي سان گڏ، انڊيڪس جي کوٽ جي نشاندهي ڪري سگهجي ٿي سوالن جي منصوبن کي پارس ڪرڻ يا سسٽم ڏسڻ جي انگن اکرن کي گڏ ڪرڻ لاءِ اشارو ذريعي MS SQL سرور:
توھان ٽيبل اشارا ۽ شقون استعمال نٿا ڪري سگھو OPTION
سائيڪل سان ڪم ڪرڻ جو ڪو به امڪان ناهي
مختلف جدولن مان هڪ ڏيک ۾ ڊيٽا کي ظاهر ڪرڻ ناممڪن آهي
اهو ياد رکڻ ضروري آهي ته انڊيڪس ٿيل ڏيک استعمال ڪرڻ جو حقيقي فائدو صرف ان کي اصل ۾ ترتيب ڏيڻ سان حاصل ڪري سگهجي ٿو.
پر جڏهن ڪنهن ڏيک کي سڏين ٿا، اهي انڊيڪس استعمال نٿا ڪري سگهجن، ۽ انهن کي واضح طور تي استعمال ڪرڻ لاءِ، توهان کي وضاحت ڪرڻ گهرجي سان (NOEXPAND).
کان وٺي LINQ سوال ٽيبل جي اشارن جي وضاحت ڪرڻ ناممڪن آهي، تنهنڪري توهان کي هڪ ٻيو نمائندگي ٺاهڻو پوندو - هيٺ ڏنل فارم جو "لپڻ":
CREATE VIEW ИМЯ_представления AS SELECT * FROM MAT_VIEW WITH (NOEXPAND);
4) ٽيبل افعال استعمال ڪندي
اڪثر ۾ LINQ سوال ذيلي سوالن جا وڏا بلاڪ يا بلاڪ هڪ پيچيده ڍانچي سان نظرين کي استعمال ڪندي هڪ انتهائي پيچيده ۽ ذيلي اختياري عمل جي جوڙجڪ سان حتمي سوال ٺاهيندا آهن.
۾ ٽيبل فنڪشن استعمال ڪرڻ جا اهم فائدا LINQ سوال:
قابليت، جيئن ته نظرن جي صورت ۾، استعمال ڪيو وڃي ۽ هڪ اعتراض جي طور تي بيان ڪيو وڃي، پر توهان ان پٽ پيٽرولر جو هڪ سيٽ پاس ڪري سگهو ٿا: فنڪشن کان (@param1، @param2 ...)
نتيجي طور، لچڪدار ڊيٽا نموني حاصل ڪري سگھجي ٿو
ٽيبل جي فنڪشن کي استعمال ڪرڻ جي صورت ۾، مٿي بيان ڪيل انڊيڪس ٿيل نظرين جي صورت ۾ اهڙيون مضبوط پابنديون نه آهن:
ٽيبل اشارو:
через لنڪ توھان وضاحت نٿا ڪري سگھو ته ڪھڙا انڊيڪس استعمال ڪيا وڃن ۽ پڇا ڳاڇا ڪرڻ وقت ڊيٽا جي اڪيلائي جي سطح کي طئي ڪيو وڃي.
پر فنڪشن ۾ اهي صلاحيتون آهن.
فنڪشن سان، توهان حاصل ڪري سگهو ٿا هڪ مسلسل مسلسل عملدرآمد سوال جو منصوبو، جتي انڊيڪس ۽ ڊيٽا جي الڳ ڪرڻ جي سطحن سان ڪم ڪرڻ جا قاعدا بيان ڪيا ويا آهن.
فنڪشن کي استعمال ڪرڻ جي اجازت ڏئي ٿو، ترتيب ڏنل نظرن جي مقابلي ۾، حاصل ڪرڻ لاء:
پيچيده ڊيٽا نموني منطق (جيتوڻيڪ لوپ استعمال ڪندي)
ڪيترن ئي مختلف جدولن مان ڊيٽا حاصل ڪرڻ
جي استعمال يونين и وجودَ
پيش OPTION تمام مفيد جڏهن اسان کي هڪجهڙائي ڪنٽرول مهيا ڪرڻ جي ضرورت آهي اختيار (MAXDOP N)، سوال جي عمل جي منصوبي جو حڪم. مثال طور:
توھان وضاحت ڪري سگھو ٿا زبردستي ٻيهر ٺاھڻ جو سوال پلان اختيار (ٻيهر ڪمپيل)
توھان وضاحت ڪري سگھوٿا ته سوال ۾ بيان ڪيل شامل آرڊر استعمال ڪرڻ لاءِ سوال جي منصوبي کي مجبور ڪيو وڃي اختيار (فورس آرڊر)
تمام تنگ ۽ سڀ کان وڌيڪ گهربل ڊيٽا سلائس استعمال ڪندي:
ڪيش ۾ وڏي ڊيٽا سيٽ کي ذخيرو ڪرڻ جي ڪا ضرورت ناهي (جيئن ته انڊيڪس ٿيل نظارن جي صورت ۾ آهي)، جنهن مان توهان اڃا تائين ڊيٽا کي پيٽرولر ذريعي فلٽر ڪرڻ جي ضرورت آهي.
مثال طور، ھڪڙو ٽيبل آھي جنھن جو فلٽر جڏهن ٽي شعبا استعمال ڪيا ويا آهن (a, b, c).
روايتي طور تي، سڀني درخواستن کي مستقل حالت آهي a = 0 ۽ ب = 0.
بهرحال، فيلڊ جي درخواست c وڌيڪ متغير.
ڏيو شرط a = 0 ۽ ب = 0 اهو واقعي اسان کي گهربل نتيجن جي سيٽ کي هزارين رڪارڊ تائين محدود ڪرڻ ۾ مدد ڪري ٿو، پر شرط تي с چونڊ کي سؤ رڪارڊ تائين محدود ڪري ٿو.
هتي ٽيبل فنڪشن هڪ بهتر اختيار ٿي سگهي ٿو.
انهي سان گڏ، هڪ ٽيبل فنڪشن وڌيڪ متوقع آهي ۽ عملدرآمد جي وقت ۾ مسلسل.
مثال
اچو ته مثال جي طور تي سوالن جي ڊيٽابيس کي استعمال ڪندي مثال تي عمل درآمد کي ڏسو.
هڪ عرض آهي چونڊيو، جيڪو ڪيترن ئي جدولن کي گڏ ڪري ٿو ۽ هڪ ڏيک استعمال ڪري ٿو (آپريٽو سوالن)، جنهن ۾ وابستگي جي جانچ ڪئي وئي آهي اي ميل ذريعي (ذريعي وجودَ"آپريٽو سوالن" ڏانهن:
درخواست نمبر 1
(@p__linq__0 nvarchar(4000))SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Join2].[Object_Id] AS [Object_Id],
[Join2].[ObjectType_Id] AS [ObjectType_Id],
[Join2].[Name] AS [Name],
[Join2].[ExternalId] AS [ExternalId]
FROM [dbo].[Questions] AS [Extent1]
INNER JOIN (SELECT [Extent2].[Object_Id] AS [Object_Id],
[Extent2].[Question_Id] AS [Question_Id], [Extent3].[ExternalId] AS [ExternalId],
[Extent3].[ObjectType_Id] AS [ObjectType_Id], [Extent4].[Name] AS [Name]
FROM [dbo].[ObjectQuestions] AS [Extent2]
INNER JOIN [dbo].[Objects] AS [Extent3] ON [Extent2].[Object_Id] = [Extent3].[Id]
LEFT OUTER JOIN [dbo].[ObjectTypes] AS [Extent4]
ON [Extent3].[ObjectType_Id] = [Extent4].[Id] ) AS [Join2]
ON [Extent1].[Id] = [Join2].[Question_Id]
WHERE ([Extent1].[AnswerId] IS NULL) AND (0 = [Extent1].[Exp]) AND ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[OperativeQuestions] AS [Extent5]
WHERE (([Extent5].[Email] = @p__linq__0) OR (([Extent5].[Email] IS NULL)
AND (@p__linq__0 IS NULL))) AND ([Extent5].[Id] = [Extent1].[Id])
));
نظارو هڪ پيچيده جوڙجڪ آهي: ان ۾ ذيلي پڇا ڳاڇا شامل آهن ۽ ترتيب ڏيڻ کي استعمال ڪري ٿو ڊسٽينڪ، جيڪو عام طور تي هڪ انتهائي وسيلن وارو آپريشن آهي.
OperativeQuestions مان هڪ نمونو اٽڪل ڏهه هزار رڪارڊ آهي.
هن سوال سان گڏ بنيادي مسئلو اهو آهي ته ٻاهرين سوالن جي رڪارڊ لاء، هڪ اندروني ذيلي سوال [OperativeQuestions] ڏيک تي عمل ڪيو ويندو آهي، جيڪو [اي ميل] = @p__linq__0 لاء اسان کي اجازت ڏئي ٿو ته اسان کي ٻاھرين چونڊ کي محدود ڪرڻ جي اجازت ڏيو (ذريعي وجودَ) سوين رڪارڊ تائين.
۽ اهو لڳي سگھي ٿو ته ذيلي پڇاڙيءَ کي [اي ميل] = @p__linq__0 ذريعي هڪ ڀيرو رڪارڊ جو حساب ڏيڻ گهرجي، ۽ پوءِ اهي ٻه سئو رڪارڊ سوالن سان Id سان ڳنڍڻ گهرجن، ۽ سوال تيز ٿي ويندا.
حقيقت ۾، سڀني جدولن جو هڪ ترتيب وار ڪنيڪشن آهي: OperativeQuestions کان Id سان Id سوالن جي خط و ڪتابت کي جانچڻ، ۽ اي ميل ذريعي فلٽر ڪرڻ.
درحقيقت، درخواست سڀني ڏهن هزارن آپريٽو سوالن جي رڪارڊ سان ڪم ڪري ٿي، پر صرف دلچسپي جي ڊيٽا جي ضرورت آهي اي ميل ذريعي.
آپريٽو سوالن جو متن ڏسو:
درخواست نمبر 2
CREATE VIEW [dbo].[OperativeQuestions]
AS
SELECT DISTINCT Q.Id, USR.email AS Email
FROM [dbo].Questions AS Q INNER JOIN
[dbo].ProcessUserAccesses AS BPU ON BPU.ProcessId = CQ.Process_Id
OUTER APPLY
(SELECT 1 AS HasNoObjects
WHERE NOT EXISTS
(SELECT 1
FROM [dbo].ObjectUserAccesses AS BOU
WHERE BOU.ProcessUserAccessId = BPU.[Id] AND BOU.[To] IS NULL)
) AS BO INNER JOIN
[dbo].Users AS USR ON USR.Id = BPU.UserId
WHERE CQ.[Exp] = 0 AND CQ.AnswerId IS NULL AND BPU.[To] IS NULL
AND (BO.HasNoObjects = 1 OR
EXISTS (SELECT 1
FROM [dbo].ObjectUserAccesses AS BOU INNER JOIN
[dbo].ObjectQuestions AS QBO
ON QBO.[Object_Id] =BOU.ObjectId
WHERE BOU.ProcessUserAccessId = BPU.Id
AND BOU.[To] IS NULL AND QBO.Question_Id = CQ.Id));
DbContext (اي ايف ڪور 2) ۾ شروعاتي ڏيک نقشي سازي
public class QuestionsDbContext : DbContext
{
//...
public DbQuery<OperativeQuestion> OperativeQuestions { get; set; }
//...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Query<OperativeQuestion>().ToView("OperativeQuestions");
}
}
ھن خاص صورت ۾، اسان ھن مسئلي جي حل تي غور ڪري رھيا آھيون بنيادي ڍانچي جي تبديلين کان سواءِ، ھڪ الڳ جدول متعارف ڪرائڻ کان سواءِ، تيار ڪيل نتيجن سان گڏ ھڪ الڳ جدول (“فعال سوال”)، جنھن کي ڊيٽا سان ڀرڻ ۽ ان کي اپڊيٽ رکڻ لاءِ ھڪ ميکانيزم جي ضرورت پوندي. .
جيتوڻيڪ اهو هڪ سٺو حل آهي، هن مسئلي کي بهتر ڪرڻ لاء هڪ ٻيو اختيار آهي.
ان پٽ پيٽرول جي طور تي اي ميل موڪلڻ سان، اسان قدرن جي جدول واپس حاصل ڪندا آهيون:
درخواست نمبر 3
CREATE FUNCTION [dbo].[OperativeQuestionsUserMail]
(
@Email nvarchar(4000)
)
RETURNS
@tbl TABLE
(
[Id] uniqueidentifier,
[Email] nvarchar(4000)
)
AS
BEGIN
INSERT INTO @tbl ([Id], [Email])
SELECT Id, @Email
FROM [OperativeQuestions] AS [x] WHERE [x].[Email] = @Email;
RETURN;
END
هي واپسي جدول جي قدرن سان اڳواٽ بيان ڪيل ڊيٽا جي جوڙجڪ سان.
OperativeQuestionsUserMail لاءِ سوالن لاءِ بھترين ۽ بھترين سوالن جا منصوبا آھن، ھڪ سخت ڍانچي جي ضرورت آھي، ۽ نه واپسي جي طور تي واپسي ٽيبل...
انهي صورت ۾، گهربل سوال 1 کي سوال 4 ۾ تبديل ڪيو ويو آهي:
درخواست نمبر 4
(@p__linq__0 nvarchar(4000))SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Join2].[Object_Id] AS [Object_Id],
[Join2].[ObjectType_Id] AS [ObjectType_Id],
[Join2].[Name] AS [Name],
[Join2].[ExternalId] AS [ExternalId]
FROM (
SELECT Id, Email FROM [dbo].[OperativeQuestionsUserMail] (@p__linq__0)
) AS [Extent0]
INNER JOIN [dbo].[Questions] AS [Extent1] ON([Extent0].Id=[Extent1].Id)
INNER JOIN (SELECT [Extent2].[Object_Id] AS [Object_Id], [Extent2].[Question_Id] AS [Question_Id], [Extent3].[ExternalId] AS [ExternalId], [Extent3].[ObjectType_Id] AS [ObjectType_Id], [Extent4].[Name] AS [Name]
FROM [dbo].[ObjectQuestions] AS [Extent2]
INNER JOIN [dbo].[Objects] AS [Extent3] ON [Extent2].[Object_Id] = [Extent3].[Id]
LEFT OUTER JOIN [dbo].[ObjectTypes] AS [Extent4]
ON [Extent3].[ObjectType_Id] = [Extent4].[Id] ) AS [Join2]
ON [Extent1].[Id] = [Join2].[Question_Id]
WHERE ([Extent1].[AnswerId] IS NULL) AND (0 = [Extent1].[Exp]);
DbContext (EF Core 2) ۾ نقشي جا نقشا ۽ افعال
public class QuestionsDbContext : DbContext
{
//...
public DbQuery<OperativeQuestion> OperativeQuestions { get; set; }
//...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Query<OperativeQuestion>().ToView("OperativeQuestions");
}
}
public static class FromSqlQueries
{
public static IQueryable<OperativeQuestion> GetByUserEmail(this DbQuery<OperativeQuestion> source, string Email)
=> source.FromSql($"SELECT Id, Email FROM [dbo].[OperativeQuestionsUserMail] ({Email})");
}