การแนะนำ
В
ที่นี่เรายังนำเสนอแนวทางเพิ่มเติมในการเพิ่มประสิทธิภาพโค้ดที่เกี่ยวข้องด้วย สอบถาม LINQ.
รู้จักกันในนามว่า ลิงค์(Language-Integrated Query) เป็นภาษาที่ง่ายและสะดวกสำหรับการสืบค้นแหล่งข้อมูล
А LINQ เป็น SQL เป็นเทคโนโลยีในการเข้าถึงข้อมูลใน DBMS นี่เป็นเครื่องมืออันทรงพลังสำหรับการทำงานกับข้อมูล โดยที่การสืบค้นจะถูกสร้างขึ้นผ่านภาษาที่เปิดเผย ซึ่งจากนั้นจะถูกแปลงเป็น แบบสอบถาม SQL แพลตฟอร์มและส่งไปยังเซิร์ฟเวอร์ฐานข้อมูลเพื่อดำเนินการ ในกรณีของเรา โดย DBMS เราหมายถึง เซิร์ฟเวอร์ MS SQL.
อย่างไรก็ตาม สอบถาม LINQ จะไม่ถูกแปลงเป็นข้อความที่เขียนอย่างเหมาะสมที่สุด แบบสอบถาม SQLซึ่ง DBA ที่มีประสบการณ์สามารถเขียนได้โดยคำนึงถึงความแตกต่างของการปรับให้เหมาะสมทั้งหมด แบบสอบถาม SQL:
- การเชื่อมต่อที่เหมาะสมที่สุด (สมัคร) และการกรองผลลัพธ์ (WHERE)
- ความแตกต่างมากมายในการใช้การเชื่อมต่อและเงื่อนไขกลุ่ม
- เงื่อนไขการเปลี่ยนที่หลากหลาย IN บน มีอยู่и ไม่อยู่ใน, <> เปิด มีอยู่
- การแคชผลลัพธ์ระดับกลางผ่านตารางชั่วคราว, CTE, ตัวแปรตาราง
- การใช้ประโยค (ทางเลือกที่) พร้อมคำแนะนำและคำแนะนำตาราง กับ (... )
- การใช้มุมมองที่จัดทำดัชนีเป็นวิธีหนึ่งในการกำจัดการอ่านข้อมูลที่ซ้ำซ้อนระหว่างการเลือก
คอขวดประสิทธิภาพหลักของผลลัพธ์ แบบสอบถาม SQL เมื่อรวบรวม สอบถาม LINQ พวกเขาคือ
- การรวมกลไกการเลือกข้อมูลทั้งหมดไว้ในคำขอเดียว
- การทำซ้ำบล็อกโค้ดที่เหมือนกัน ซึ่งท้ายที่สุดจะนำไปสู่การอ่านข้อมูลที่ไม่จำเป็นหลายครั้งในที่สุด
- กลุ่มของเงื่อนไขหลายองค์ประกอบ (ตรรกะ "และ" และ "หรือ") - AND и ORเมื่อรวมเข้ากับเงื่อนไขที่ซับซ้อน นำไปสู่ความจริงที่ว่าเครื่องมือเพิ่มประสิทธิภาพซึ่งมีดัชนีที่ไม่ใช่คลัสเตอร์ที่เหมาะสมสำหรับฟิลด์ที่จำเป็น ในที่สุดก็เริ่มสแกนเทียบกับดัชนีคลัสเตอร์ (สแกนดัชนี) ตามกลุ่มเงื่อนไข
- การซ้อนแบบสอบถามย่อยแบบลึกทำให้การแยกวิเคราะห์เป็นปัญหามาก คำสั่ง SQL และการวิเคราะห์แผนการสืบค้นในส่วนของนักพัฒนาและ DBA
วิธีการเพิ่มประสิทธิภาพ
ตอนนี้เรามาดูวิธีการปรับให้เหมาะสมโดยตรงกัน
1) การจัดทำดัชนีเพิ่มเติม
วิธีที่ดีที่สุดคือพิจารณาตัวกรองในตารางการเลือกหลัก เนื่องจากบ่อยครั้งที่แบบสอบถามทั้งหมดถูกสร้างขึ้นโดยใช้ตารางหลักหนึ่งหรือสองตาราง (แอปพลิเคชัน-บุคคล-การดำเนินการ) และมีชุดเงื่อนไขมาตรฐาน (ปิด ยกเลิก เปิดใช้งาน สถานะ) สิ่งสำคัญคือต้องสร้างดัชนีที่เหมาะสมสำหรับกลุ่มตัวอย่างที่ระบุ
โซลูชันนี้เหมาะสมเมื่อเลือกฟิลด์เหล่านี้เพื่อจำกัดชุดที่ส่งคืนให้กับแบบสอบถามอย่างมาก
เช่น เรามีใบสมัคร 500000 ใบ อย่างไรก็ตาม มีแอปพลิเคชันที่ใช้งานอยู่เพียง 2000 รายการเท่านั้น จากนั้นดัชนีที่เลือกอย่างถูกต้องจะช่วยเราจาก สแกนดัชนี บนโต๊ะขนาดใหญ่และจะช่วยให้คุณสามารถเลือกข้อมูลได้อย่างรวดเร็วผ่านดัชนีที่ไม่ใช่คลัสเตอร์
นอกจากนี้ การขาดดัชนีสามารถระบุได้ผ่านพร้อมท์สำหรับการแยกวิเคราะห์แผนการสืบค้นหรือการรวบรวมสถิติมุมมองของระบบ เซิร์ฟเวอร์ MS SQL:
ข้อมูลมุมมองทั้งหมดมีข้อมูลเกี่ยวกับดัชนีที่ขาดหายไป ยกเว้นดัชนีเชิงพื้นที่
อย่างไรก็ตาม ดัชนีและแคชมักเป็นวิธีจัดการกับผลที่ตามมาของการเขียนที่ไม่ดี สอบถาม LINQ и แบบสอบถาม SQL.
ดังที่แสดงให้เห็นวิถีชีวิตอันโหดร้าย บ่อยครั้งที่ธุรกิจต้องใช้คุณลักษณะทางธุรกิจภายในกำหนดเวลาที่แน่นอน ดังนั้นคำขอจำนวนมากจึงมักถูกถ่ายโอนไปยังพื้นหลังด้วยการแคช
นี่เป็นเหตุผลบางส่วน เนื่องจากผู้ใช้ไม่ต้องการข้อมูลล่าสุดเสมอไป และอินเทอร์เฟซผู้ใช้มีระดับการตอบสนองที่ยอมรับได้
แนวทางนี้ช่วยให้สามารถแก้ไขความต้องการทางธุรกิจได้ แต่ท้ายที่สุดแล้วก็จะลดประสิทธิภาพของระบบข้อมูลลงโดยการชะลอการแก้ปัญหาออกไป
นอกจากนี้ยังควรจำไว้ว่าในกระบวนการค้นหาดัชนีที่จำเป็นในการเพิ่มข้อเสนอแนะ MSSQL การเพิ่มประสิทธิภาพอาจไม่ถูกต้อง รวมถึงภายใต้เงื่อนไขต่อไปนี้:
- หากมีดัชนีที่มีชุดฟิลด์คล้ายกันอยู่แล้ว
- หากเขตข้อมูลในตารางไม่สามารถจัดทำดัชนีได้เนื่องจากข้อจำกัดในการจัดทำดัชนี (อธิบายรายละเอียดเพิ่มเติม
ที่นี่ ).
2) การรวมคุณลักษณะให้เป็นคุณลักษณะใหม่เดียว
บางครั้งบางเขตข้อมูลจากตารางหนึ่งซึ่งทำหน้าที่เป็นพื้นฐานสำหรับกลุ่มเงื่อนไข สามารถถูกแทนที่ด้วยการแนะนำเขตข้อมูลใหม่หนึ่งเขต
โดยเฉพาะอย่างยิ่งสำหรับฟิลด์สถานะ ซึ่งโดยปกติจะเป็นประเภทบิตหรือจำนวนเต็ม
ตัวอย่าง:
ปิด = 0 และยกเลิก = 0 และเปิดใช้งาน = 0 ถูกแทนที่ด้วย สถานะ = 1.
นี่คือที่ที่มีการแนะนำแอ็ตทริบิวต์สถานะจำนวนเต็มเพื่อให้แน่ใจว่าสถานะเหล่านี้ถูกเติมลงในตาราง ถัดไป แอตทริบิวต์ใหม่นี้จะถูกจัดทำดัชนี
นี่เป็นวิธีแก้ปัญหาขั้นพื้นฐานสำหรับปัญหาด้านประสิทธิภาพ เนื่องจากเราเข้าถึงข้อมูลโดยไม่ต้องคำนวณโดยไม่จำเป็น
3) การทำให้เป็นรูปธรรมของมุมมอง
น่าเสียดายที่ใน สอบถาม LINQ ตารางชั่วคราว, CTE และตัวแปรตารางไม่สามารถนำมาใช้โดยตรง
อย่างไรก็ตาม มีวิธีอื่นในการเพิ่มประสิทธิภาพสำหรับกรณีนี้ - มุมมองที่จัดทำดัชนีไว้
กลุ่มเงื่อนไข (จากตัวอย่างด้านบน) ปิด = 0 และยกเลิก = 0 และเปิดใช้งาน = 0 (หรือชุดของเงื่อนไขอื่นๆ ที่คล้ายคลึงกัน) กลายเป็นตัวเลือกที่ดีในการใช้ในมุมมองที่มีการจัดทำดัชนี โดยแคชข้อมูลส่วนเล็กๆ จากชุดใหญ่
แต่มีข้อจำกัดหลายประการเมื่อทำให้มุมมองเป็นรูปธรรม:
- การใช้แบบสอบถามย่อย clauses มีอยู่ ควรเปลี่ยนมาใช้ สมัคร
- คุณไม่สามารถใช้ประโยคได้ ยูเนี่ยน, ยูเนี่ยนทั้งหมด, ข้อยกเว้น, ตัด
- คุณไม่สามารถใช้คำแนะนำและส่วนคำสั่งของตารางได้ ทางเลือกที่
- ไม่มีความเป็นไปได้ในการทำงานกับวงจร
- เป็นไปไม่ได้ที่จะแสดงข้อมูลในมุมมองเดียวจากตารางต่างๆ
สิ่งสำคัญคือต้องจำไว้ว่าประโยชน์ที่แท้จริงของการใช้มุมมองที่จัดทำดัชนีจะบรรลุได้โดยการจัดทำดัชนีจริงเท่านั้น
แต่เมื่อเรียกมุมมอง ดัชนีเหล่านี้อาจไม่สามารถใช้ได้ และหากต้องการใช้อย่างชัดเจน คุณต้องระบุ ด้วย(ไม่ขยาย).
ตั้งแต่ใน สอบถาม LINQ เป็นไปไม่ได้ที่จะกำหนดคำแนะนำตาราง ดังนั้นคุณต้องสร้างการนำเสนออื่น - "wrapper" ของแบบฟอร์มต่อไปนี้:
CREATE VIEW ИМЯ_представления AS SELECT * FROM MAT_VIEW WITH (NOEXPAND);
4) การใช้ฟังก์ชันตาราง
มักจะเข้า. สอบถาม LINQ บล็อกขนาดใหญ่ของแบบสอบถามย่อยหรือบล็อกที่ใช้มุมมองที่มีโครงสร้างที่ซับซ้อนก่อให้เกิดการสืบค้นขั้นสุดท้ายที่มีโครงสร้างการดำเนินการที่ซับซ้อนมากและด้อยประสิทธิภาพ
ประโยชน์หลักของการใช้ฟังก์ชันตารางใน สอบถาม LINQ:
- ความสามารถ ในกรณีของมุมมอง ที่จะใช้และระบุเป็นออบเจ็กต์ แต่คุณสามารถส่งชุดของพารามิเตอร์อินพุตได้:
จาก FUNCTION(@param1, @param2 ...)
ส่งผลให้สามารถสุ่มตัวอย่างข้อมูลที่ยืดหยุ่นได้ - ในกรณีของการใช้ฟังก์ชันตาราง ไม่มีข้อจำกัดที่เข้มงวดเช่นในกรณีของมุมมองที่จัดทำดัชนีไว้ตามที่อธิบายไว้ข้างต้น:
- คำแนะนำตาราง:
ตลอด ลิงค์ คุณไม่สามารถระบุได้ว่าควรใช้ดัชนีใดและกำหนดระดับการแยกข้อมูลเมื่อทำการสืบค้น
แต่ฟังก์ชันมีความสามารถเหล่านี้
ด้วยฟังก์ชันนี้ คุณสามารถบรรลุแผนการสืบค้นการดำเนินการที่ค่อนข้างคงที่ โดยมีการกำหนดกฎสำหรับการทำงานกับดัชนีและระดับการแยกข้อมูล - การใช้ฟังก์ชันนี้ช่วยให้ได้รับ: เมื่อเปรียบเทียบกับมุมมองที่จัดทำดัชนีแล้ว
- ตรรกะการสุ่มตัวอย่างข้อมูลที่ซับซ้อน (แม้จะใช้ลูป)
- ดึงข้อมูลจากตารางต่างๆ มากมาย
- ใช้ ยูเนี่ยน и มีอยู่
- คำแนะนำตาราง:
- เสนอ ทางเลือกที่ มีประโยชน์มากเมื่อเราต้องการควบคุมการทำงานพร้อมกัน ตัวเลือก(MAXDOP N)ลำดับของแผนการดำเนินการแบบสอบถาม ตัวอย่างเช่น:
- คุณสามารถระบุการบังคับให้สร้างแผนการสืบค้นใหม่ได้ ตัวเลือก (คอมไพล์ใหม่)
- คุณสามารถระบุว่าจะบังคับให้แผนแบบสอบถามใช้ลำดับการรวมที่ระบุในแบบสอบถามหรือไม่ ตัวเลือก (บังคับสั่ง)
รายละเอียดเพิ่มเติมเกี่ยวกับ ทางเลือกที่ อธิบายไว้
ที่นี่ . - การใช้ส่วนข้อมูลที่แคบที่สุดและจำเป็นที่สุด:
ไม่จำเป็นต้องจัดเก็บชุดข้อมูลขนาดใหญ่ในแคช (เช่นเดียวกับกรณีที่มีมุมมองที่จัดทำดัชนี) ซึ่งคุณยังคงต้องกรองข้อมูลตามพารามิเตอร์
ตัวอย่างเช่น มีตารางที่มีตัวกรอง WHERE มีการใช้สามฟิลด์ (ก ข ค).ตามอัตภาพ คำขอทั้งหมดจะมีเงื่อนไขคงที่ a = 0 และ b = 0.
อย่างไรก็ตามการขอลงสนาม c ตัวแปรมากขึ้น
ปล่อยให้มีสภาพ a = 0 และ b = 0 ช่วยให้เราจำกัดชุดผลลัพธ์ที่ต้องการเป็นหลายพันเรกคอร์ดได้จริง แต่เปิดเงื่อนไขไว้ с จำกัดการเลือกให้เหลือเพียงร้อยบันทึก
ฟังก์ชันตารางอาจเป็นตัวเลือกที่ดีกว่า
นอกจากนี้ ฟังก์ชันตารางยังคาดเดาได้มากขึ้นและสม่ำเสมอในเวลาดำเนินการอีกด้วย
ตัวอย่าง
ลองดูตัวอย่างการใช้งานโดยใช้ฐานข้อมูลคำถามเป็นตัวอย่าง
มีเรื่องขอ SELECTซึ่งรวมหลายตารางและใช้มุมมองเดียว (OperativeQuestions) ซึ่งตรวจสอบความเกี่ยวข้องทางอีเมล (ผ่าน มีอยู่) ถึง “คำถามเชิงปฏิบัติการ”:
คำขอหมายเลข 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])
));
มุมมองมีโครงสร้างที่ค่อนข้างซับซ้อน: มีการรวมแบบสอบถามย่อยและใช้การเรียงลำดับ DISTINCTซึ่งโดยทั่วไปเป็นการดำเนินการที่ค่อนข้างใช้ทรัพยากรมาก
ตัวอย่างจาก OperativeQuestions มีประมาณหนึ่งหมื่นบันทึก
ปัญหาหลักของแบบสอบถามนี้คือสำหรับบันทึกจากการสืบค้นภายนอก แบบสอบถามย่อยภายในจะถูกดำเนินการในมุมมอง [OperativeQuestions] ซึ่งควรสำหรับ [Email] = @p__linq__0 อนุญาตให้เราจำกัดการเลือกผลลัพธ์ (ผ่าน มีอยู่) มากถึงหลายร้อยรายการ
และอาจดูเหมือนว่าแบบสอบถามย่อยควรคำนวณบันทึกหนึ่งครั้งโดย [Email] = @p__linq__0 จากนั้นบันทึกสองสามร้อยรายการเหล่านี้ควรเชื่อมต่อด้วย Id กับคำถาม และการสืบค้นจะรวดเร็ว
ในความเป็นจริง มีการเชื่อมต่อตามลำดับของตารางทั้งหมด: การตรวจสอบความสอดคล้องของคำถาม Id กับ Id จาก OperativeQuestions และการกรองทางอีเมล
ที่จริงแล้ว คำขอดังกล่าวใช้ได้กับบันทึก OperativeQuestions ทั้งหมดนับหมื่นรายการ แต่ต้องการเฉพาะข้อมูลที่สนใจทางอีเมลเท่านั้น
ข้อความดู OperationQuestions:
คำขอหมายเลข 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 (EF Core 2)
public class QuestionsDbContext : DbContext
{
//...
public DbQuery<OperativeQuestion> OperativeQuestions { get; set; }
//...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Query<OperativeQuestion>().ToView("OperativeQuestions");
}
}
แบบสอบถาม LINQ เริ่มต้น
var businessObjectsData = await context
.OperativeQuestions
.Where(x => x.Email == Email)
.Include(x => x.Question)
.Select(x => x.Question)
.SelectMany(x => x.ObjectQuestions,
(x, bo) => new
{
Id = x.Id,
ObjectId = bo.Object.Id,
ObjectTypeId = bo.Object.ObjectType.Id,
ObjectTypeName = bo.Object.ObjectType.Name,
ObjectExternalId = bo.Object.ExternalId
})
.ToListAsync();
ในกรณีเฉพาะนี้ เรากำลังพิจารณาวิธีแก้ไขปัญหานี้โดยไม่มีการเปลี่ยนแปลงโครงสร้างพื้นฐาน โดยไม่ต้องแนะนำตารางแยกต่างหากพร้อมผลลัพธ์สำเร็จรูป (“แบบสอบถามที่ใช้งานอยู่”) ซึ่งจะต้องใช้กลไกในการกรอกข้อมูลและรักษาให้ทันสมัยอยู่เสมอ .
แม้ว่านี่จะเป็นวิธีแก้ปัญหาที่ดี แต่ก็มีอีกทางเลือกหนึ่งในการเพิ่มประสิทธิภาพปัญหานี้
วัตถุประสงค์หลักคือการแคชรายการโดย [Email] = @p__linq__0 จากมุมมอง OperationQuestions
แนะนำฟังก์ชันตาราง [dbo].[OperativeQuestionsUserMail] ลงในฐานข้อมูล
โดยการส่งอีเมลเป็นพารามิเตอร์อินพุต เราจะได้ตารางค่ากลับมา:
คำขอหมายเลข 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 เหมาะสมที่สุดและมีแผนสืบค้นที่เหมาะสมที่สุด จำเป็นต้องมีโครงสร้างที่เข้มงวด และไม่ ส่งคืนตารางเป็นการส่งคืน...
ในกรณีนี้ Query 1 ที่จำเป็นจะถูกแปลงเป็น Query 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})");
}
แบบสอบถาม LINQ สุดท้าย
var businessObjectsData = await context
.OperativeQuestions
.GetByUserEmail(Email)
.Include(x => x.Question)
.Select(x => x.Question)
.SelectMany(x => x.ObjectQuestions,
(x, bo) => new
{
Id = x.Id,
ObjectId = bo.Object.Id,
ObjectTypeId = bo.Object.ObjectType.Id,
ObjectTypeName = bo.Object.ObjectType.Name,
ObjectExternalId = bo.Object.ExternalId
})
.ToListAsync();
ลำดับของเวลาดำเนินการลดลงจาก 200-800 ms เป็น 2-20 ms ฯลฯ กล่าวคือ เร็วขึ้นหลายสิบเท่า
หากเราพิจารณาโดยเฉลี่ยมากขึ้น แทนที่จะเป็น 350 มิลลิวินาที เราได้ 8 มิลลิวินาที
จากข้อได้เปรียบที่ชัดเจน เรายังได้รับ:
- การลดภาระการอ่านโดยทั่วไป
- ลดโอกาสในการบล็อกลงอย่างมาก
- ลดเวลาการบล็อกเฉลี่ยลงเป็นค่าที่ยอมรับได้
เอาท์พุต
การเพิ่มประสิทธิภาพและการปรับแต่งการเรียกฐานข้อมูลอย่างละเอียด MSSQL ตลอด ลิงค์ เป็นปัญหาที่สามารถแก้ไขได้
ความเอาใจใส่และความสม่ำเสมอมีความสำคัญมากในงานนี้
ที่จุดเริ่มต้นของกระบวนการ:
- จำเป็นต้องตรวจสอบข้อมูลที่คำขอทำงาน (ค่า ประเภทข้อมูลที่เลือก)
- ดำเนินการจัดทำดัชนีข้อมูลนี้อย่างเหมาะสม
- ตรวจสอบความถูกต้องของเงื่อนไขการเข้าร่วมระหว่างตาราง
การทำซ้ำการปรับให้เหมาะสมครั้งถัดไปเผยให้เห็น:
- พื้นฐานของคำขอและกำหนดตัวกรองคำขอหลัก
- ทำซ้ำบล็อกข้อความค้นหาที่คล้ายกันและวิเคราะห์จุดตัดของเงื่อนไข
- ใน SSMS หรือ GUI อื่น ๆ สำหรับ SQL Server ปรับให้เหมาะสมเอง แบบสอบถาม SQL (จัดสรรที่เก็บข้อมูลระดับกลาง สร้างแบบสอบถามผลลัพธ์โดยใช้ที่เก็บข้อมูลนี้ (อาจมีหลายอัน))
- ในขั้นตอนสุดท้ายโดยคำนึงถึงผลลัพธ์เป็นหลัก แบบสอบถาม SQL, กำลังสร้างโครงสร้างใหม่ แบบสอบถาม LINQ
ผลลัพท์ที่ได้ แบบสอบถาม LINQ ควรจะมีโครงสร้างที่เหมือนกันเพื่อระบุจุดที่เหมาะสมที่สุด แบบสอบถาม SQL จากจุดที่ 3
บลาโกดาเรนนอสตี
ขอบคุณมากสำหรับเพื่อนร่วมงาน
ที่มา: will.com