C#.NET-ում LINQ հարցումների օպտիմալացման մեթոդներ

Ներածություն

В այս հոդվածը դիտարկվել են որոշ օպտիմալացման մեթոդներ LINQ հարցումներ.
Այստեղ մենք ներկայացնում ենք կոդի օպտիմալացման ևս մի քանի մոտեցում՝ կապված LINQ հարցումներ.

Հայտնի է, որ LINQ(Language-Integrated Query) պարզ և հարմար լեզու է տվյալների աղբյուրի հարցումների համար:

А LINQ դեպի SQL DBMS-ում տվյալների մուտք գործելու տեխնոլոգիա է: Սա տվյալների հետ աշխատելու հզոր գործիք է, որտեղ հարցումները կառուցվում են դեկլարատիվ լեզվի միջոցով, որն այնուհետև կվերածվի SQL հարցումներ հարթակ և ուղարկվել տվյալների բազայի սերվեր՝ կատարման համար: Մեր դեպքում DBMS ասելով նկատի ունենք MS SQL սերվեր.

Սակայն, LINQ հարցումներ չեն վերածվում օպտիմալ գրավորների SQL հարցումներ, որը փորձառու DBA-ն կարող էր գրել օպտիմալացման բոլոր նրբություններով SQL հարցումներ:

  1. օպտիմալ կապեր (ՄԻԱՑԵՔ) և արդյունքների զտում (ՈՐՏԵՂ)
  2. բազմաթիվ նրբերանգներ կապերի և խմբային պայմանների օգտագործման մեջ
  3. փոխարինման պայմանների շատ տատանումներ IN մասին ՊԱՏԱՍԽԱՆи ՉԻ ՄԵՋ, <> միացված է ՊԱՏԱՍԽԱՆ
  4. Արդյունքների միջանկյալ քեշավորում ժամանակավոր աղյուսակների, CTE-ի, աղյուսակի փոփոխականների միջոցով
  5. նախադասության օգտագործումը (ԸՆՏՐՈՒԹՅՈՒՆ) հրահանգներով և աղյուսակի հուշումներով ՀԵՏ (...)
  6. օգտագործելով ինդեքսավորված դիտումները՝ որպես ընտրության ժամանակ ավելորդ տվյալների ընթերցումներից ազատվելու միջոցներից մեկը

Ստացվածի հիմնական կատարողական խոչընդոտները SQL հարցումներ կազմելիս LINQ հարցումներ են:

  1. տվյալների ընտրության ողջ մեխանիզմի համախմբում մեկ հարցման մեջ
  2. կոդի նույնական բլոկների կրկնօրինակում, որն ի վերջո հանգեցնում է բազմաթիվ անհարկի տվյալների ընթերցումների
  3. բազմաբաղադրիչ պայմանների խմբեր (տրամաբանական «և» և «կամ») - ԵՎ и OR, համակցվելով բարդ պայմանների մեջ, հանգեցնում է նրան, որ օպտիմիզատորը, ունենալով համապատասխան ոչ կլաստերային ինդեքսներ անհրաժեշտ դաշտերի համար, ի վերջո սկսում է սկանավորել կլաստերային ինդեքսով (INDEX Scan) ըստ պայմանների խմբերի
  4. Ենթհարցումների խորը բնադրումը շատ խնդրահարույց է դարձնում վերլուծությունը SQL հայտարարություններ և մշակողների կողմից հարցման պլանի վերլուծություն և DBA

Օպտիմալացման մեթոդներ

Այժմ եկեք անմիջապես անցնենք օպտիմալացման մեթոդներին:

1) Լրացուցիչ ինդեքսավորում

Ավելի լավ է դիտարկել զտիչները հիմնական ընտրության աղյուսակներում, քանի որ շատ հաճախ ամբողջ հարցումը կառուցված է մեկ կամ երկու հիմնական աղյուսակների շուրջ (հավելվածներ-մարդիկ-գործողություններ) և պայմանների ստանդարտ փաթեթով (Փակված է, Չեղարկված, Միացված է, Կարգավիճակ): Կարևոր է հայտնաբերված նմուշների համար ստեղծել համապատասխան ցուցանիշներ:

Այս լուծումը իմաստ ունի, երբ ընտրելով այս դաշտերը, զգալիորեն սահմանափակում է վերադարձված փաթեթը հարցմանը:

Օրինակ՝ 500000 հազար դիմում ունենք։ Այնուամենայնիվ, կա ընդամենը 2000 ակտիվ հավելված։ Այնուհետև մեզ կփրկի ճիշտ ընտրված ցուցանիշը INDEX Scan մեծ սեղանի վրա և թույլ կտա արագ ընտրել տվյալներ ոչ կլաստերային ինդեքսի միջոցով:

Նաև ինդեքսների բացակայությունը կարելի է բացահայտել հարցումների պլանների վերլուծության կամ համակարգի դիտումների վիճակագրության հավաքագրման հրահանգների միջոցով: MS SQL սերվեր:

  1. sys.dm_db_missing_index_groups
  2. sys.dm_db_missing_index_group_stats
  3. sys.dm_db_missing_index_details

Դիտման բոլոր տվյալները պարունակում են տեղեկատվություն բացակայող ինդեքսների մասին, բացառությամբ տարածական ինդեքսների:

Այնուամենայնիվ, ինդեքսները և քեշավորումը հաճախ վատ գրվածի հետևանքների դեմ պայքարի մեթոդներ են LINQ հարցումներ и SQL հարցումներ.

Ինչպես ցույց է տալիս կյանքի դաժան պրակտիկան, հաճախ բիզնեսի համար կարևոր է որոշակի ժամկետներում իրականացնել բիզնեսի առանձնահատկությունները: Եվ հետևաբար, ծանր խնդրանքները հաճախ տեղափոխվում են հետին պլան քեշավորման միջոցով:

Սա մասամբ արդարացված է, քանի որ օգտվողին միշտ չէ, որ անհրաժեշտ են վերջին տվյալները, և առկա է օգտատիրոջ միջերեսի արձագանքման ընդունելի մակարդակ:

Այս մոտեցումը թույլ է տալիս լուծել բիզնեսի կարիքները, սակայն, ի վերջո, նվազեցնում է տեղեկատվական համակարգի արդյունավետությունը՝ պարզապես հետաձգելով խնդիրների լուծումները:

Հարկ է նաև հիշել, որ ավելացնելու համար անհրաժեշտ ինդեքսների որոնման գործընթացում առաջարկներ MS SQL- ն Օպտիմալացումը կարող է սխալ լինել, ներառյալ հետևյալ պայմանները.

  1. եթե արդեն կան ինդեքսներ նմանատիպ դաշտերի հավաքածուով
  2. եթե աղյուսակի դաշտերը չեն կարող ինդեքսավորվել ինդեքսավորման սահմանափակումների պատճառով (ավելի մանրամասն նկարագրված է այստեղ).

2) ատրիբուտների միավորում մեկ նոր հատկանիշի մեջ

Երբեմն մեկ աղյուսակի որոշ դաշտեր, որոնք հիմք են հանդիսանում մի խումբ պայմանների համար, կարող են փոխարինվել մեկ նոր դաշտի ներդրմամբ:

Սա հատկապես ճիշտ է կարգավիճակի դաշտերի համար, որոնք սովորաբար տիպի բիթ կամ ամբողջ թիվ են:

Example:

Փակ է = 0 ԵՎ չեղարկված = 0 ԵՎ միացված է = 0 փոխարինվում է Կարգավիճակը = 1.

Սա այն վայրն է, որտեղ ներդրվում է ամբողջ թվի կարգավիճակ հատկանիշը, որպեսզի ապահովվի, որ այս կարգավիճակները լրացված են աղյուսակում: Հաջորդը, այս նոր հատկանիշը ինդեքսավորվում է:

Սա կատարողականի խնդրի հիմնարար լուծումն է, քանի որ մենք տվյալների մուտք ենք գործում առանց ավելորդ հաշվարկների:

3) Տեսակետի նյութականացում

Ցավոք սրտի, ներս LINQ հարցումներ Ժամանակավոր աղյուսակները, CTE-ները և աղյուսակի փոփոխականները չեն կարող ուղղակիորեն օգտագործվել:

Այնուամենայնիվ, այս դեպքի համար օպտիմալացնելու մեկ այլ տարբերակ կա՝ ինդեքսավորված դիտումներ:

Պայմանների խումբ (վերը նշված օրինակից) Փակ է = 0 ԵՎ չեղարկված = 0 ԵՎ միացված է = 0 (կամ այլ նմանատիպ պայմանների մի շարք) լավ տարբերակ է դառնում դրանք ինդեքսավորված տեսքի մեջ օգտագործելու համար՝ քեշավորելով տվյալների փոքր հատվածը մեծ հավաքածուից:

Բայց տեսակետը նյութականացնելիս կան մի շարք սահմանափակումներ.

  1. ենթհարցումների, դրույթների օգտագործումը ՊԱՏԱՍԽԱՆ պետք է փոխարինվի օգտագործելով ՄԻԱՑԵՔ
  2. չես կարող նախադասություններ օգտագործել UNION, UNION ALL- ը, ԲԱՑԱՌՈՒԹՅՈՒՆ, ԽԱECTԱECTՆԵԼ
  3. Դուք չեք կարող օգտագործել աղյուսակի ակնարկներ և կետեր ԸՆՏՐՈՒԹՅՈՒՆ
  4. ցիկլերի հետ աշխատելու հնարավորություն չկա
  5. Անհնար է տվյալներ ցուցադրել տարբեր աղյուսակներից մեկ տեսքով

Կարևոր է հիշել, որ ինդեքսավորված տեսք օգտագործելու իրական օգուտը կարելի է ձեռք բերել միայն այն իրականում ինդեքսավորելով:

Բայց դիտում կանչելիս այս ինդեքսները կարող են չօգտագործվել, և դրանք բացահայտ օգտագործելու համար պետք է նշեք. WITH (NOEXPAND).

Քանի որ LINQ հարցումներ Անհնար է սահմանել աղյուսակի ակնարկներ, այնպես որ դուք պետք է ստեղծեք մեկ այլ ներկայացուցչություն՝ հետևյալ ձևի «փաթաթան».

CREATE VIEW ИМЯ_представления AS SELECT * FROM MAT_VIEW WITH (NOEXPAND);

4) Սեղանի գործառույթների օգտագործումը

Հաճախ ներս LINQ հարցումներ Ենթահարկերի կամ բլոկների մեծ բլոկները, որոնք օգտագործում են բարդ կառուցվածքով դիտումներ, ձևավորում են վերջնական հարցումը շատ բարդ և ոչ օպտիմալ կատարման կառուցվածքով:

Սեղանի գործառույթների օգտագործման հիմնական առավելությունները LINQ հարցումներ:

  1. Հնարավորություն, ինչպես դիտումների դեպքում, օգտագործվելու և նշվելու որպես օբյեկտ, բայց դուք կարող եք փոխանցել մուտքային պարամետրերի մի շարք.
    FROM FUNCTION (@param1, @param2 ...)
    Արդյունքում կարելի է ձեռք բերել տվյալների ճկուն նմուշառում
  2. Աղյուսակային ֆունկցիայի օգտագործման դեպքում չկան այնպիսի խիստ սահմանափակումներ, ինչպիսին վերը նկարագրված ինդեքսավորված դիտումների դեպքում.
    1. Աղյուսակի հուշումներ.
      միջոցով LINQ Դուք չեք կարող նշել, թե որ ինդեքսները պետք է օգտագործվեն և հարցումներ կատարելիս որոշել տվյալների մեկուսացման մակարդակը:
      Բայց ֆունկցիան ունի այս հնարավորությունները։
      Գործառույթի միջոցով դուք կարող եք հասնել բավականին մշտական ​​կատարման հարցման պլանի, որտեղ սահմանվում են ինդեքսների հետ աշխատելու կանոններ և տվյալների մեկուսացման մակարդակներ:
    2. Ֆունկցիան օգտագործելը թույլ է տալիս, համեմատած ինդեքսավորված դիտումների հետ, ստանալ.
      • բարդ տվյալների նմուշառման տրամաբանություն (նույնիսկ օղակների օգտագործմամբ)
      • բազմաթիվ տարբեր աղյուսակներից տվյալներ ստանալը
      • օգտագործումը UNION и ՊԱՏԱՍԽԱՆ

  3. Առաջարկ ԸՆՏՐՈՒԹՅՈՒՆ շատ օգտակար է, երբ մենք պետք է ապահովենք համաժամանակյա հսկողություն OPTION (MAXDOP N), հարցումների կատարման պլանի կարգը։ Օրինակ:
    • կարող եք նշել հարցման պլանի հարկադիր վերստեղծում ՏԱՐԲԵՐԱԿ (ՎԵՐԿՈՄՊԻԼԵԼ)
    • դուք կարող եք նշել, թե արդյոք ստիպել հարցման պլանին օգտագործել հարցման մեջ նշված միացման կարգը ՏԱՐԲԵՐԱԿ (ՊԱՐՏԱԴԻՐ ՊԱՏՎԻՐ)

    մասին ավելի մանրամասն ԸՆՏՐՈՒԹՅՈՒՆ նկարագրված է այստեղ.

  4. Օգտագործելով ամենանեղ և պահանջվող տվյալների հատվածը.
    Տվյալների մեծ հավաքածուները քեշերում պահելու կարիք չկա (ինչպես ինդեքսավորված դիտումների դեպքում), որոնցից դեռ պետք է զտել տվյալները ըստ պարամետրի։
    Օրինակ, կա սեղան, որի զտիչը ՈՐՏԵՂ օգտագործվում է երեք դաշտ (ա, բ, գ).

    Պայմանականորեն, բոլոր խնդրանքները ունեն մշտական ​​պայման a = 0 և b = 0.

    Այնուամենայնիվ, դաշտի խնդրանքը c ավելի փոփոխական:

    Թող պայմանը a = 0 և b = 0 Դա իսկապես օգնում է մեզ սահմանափակել անհրաժեշտ արդյունքի հավաքածուն հազարավոր ռեկորդներով, բայց պայմանը с նեղացնում է ընտրությունը մինչև հարյուր ռեկորդ:

    Այստեղ սեղանի գործառույթը կարող է ավելի լավ տարբերակ լինել:

    Բացի այդ, աղյուսակի ֆունկցիան ավելի կանխատեսելի և հետևողական է կատարման ժամանակում:

օրինակները

Եկեք նայենք իրականացման օրինակին, օգտագործելով Questions տվյալների բազան որպես օրինակ:

Կա խնդրանք 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])
));

Տեսարանը բավականին բարդ կառուցվածք ունի. այն պարունակում է ենթհարցերի միացումներ և օգտագործում է տեսակավորում պարզ, որն ընդհանուր առմամբ բավականին ռեսուրսատար գործողություն է։

OperativeQuestions-ի նմուշը մոտ տասը հազար գրառում է:

Այս հարցման հիմնական խնդիրն այն է, որ արտաքին հարցման գրառումների համար ներքին ենթահարկ է կատարվում [OperativeQuestions] տեսքի վրա, որը [Email] = @p__linq__0-ի համար պետք է թույլ տա մեզ սահմանափակել ելքային ընտրությունը (միջոցով ՊԱՏԱՍԽԱՆ) մինչև հարյուրավոր գրառումներ:

Եվ կարող է թվալ, որ ենթհարցումը պետք է մեկ անգամ հաշվարկի գրառումները [Email] = @p__linq__0-ով, այնուհետև այս երկու հարյուր գրառումները պետք է Id-ով միացվեն Questions-ով, և հարցումը արագ կլինի:

Փաստորեն, կա բոլոր աղյուսակների հաջորդական կապը՝ ստուգում է Id Questions-ի համապատասխանությունը Id-ի հետ OperativeQuestions-ից և զտում էլփոստով:

Փաստորեն, հարցումն աշխատում է OperativeQuestions-ի բոլոր տասնյակ հազարավոր գրառումների հետ, բայց միայն հետաքրքրող տվյալները անհրաժեշտ են Էլփոստի միջոցով:

OperativeQuestions դիտել տեքստը.

Հարցում թիվ 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 գրառումները OperativeQuestions տեսքից:

Ներդրեք աղյուսակի ֆունկցիան [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-ին լինեն օպտիմալ և ունենան հարցումների օպտիմալ պլաններ, անհրաժեշտ է խիստ կառուցվածք, և ոչ ՎԵՐԱԴԱՐՁՆՈՒՄ Է ՍԵՂԱՆԱԿԸ ՈՐՊԵՍ ՎԵՐԱԴԱՐՁ...

Այս դեպքում պահանջվող հարցումը 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})");
}

Վերջնական 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 մվ-ից մինչև 2-20 մվ և այլն, այսինքն՝ տասնյակ անգամ ավելի արագ:

Եթե ​​ավելի միջին ընդունենք, ապա 350 ms-ի փոխարեն ստացանք 8 ms։

Ակնհայտ առավելություններից մենք նաև ստանում ենք.

  1. ընթերցանության բեռի ընդհանուր նվազում,
  2. արգելափակման հավանականության զգալի նվազում
  3. նվազեցնելով արգելափակման միջին ժամանակը մինչև ընդունելի արժեքներ

Արտադրողականություն

Տվյալների բազայի զանգերի օպտիմալացում և ճշգրտում MS SQL- ն միջոցով LINQ խնդիր է, որը կարելի է լուծել:

Այս աշխատանքում շատ կարևոր է ուշադրությունն ու հետևողականությունը։

Գործընթացի սկզբում.

  1. անհրաժեշտ է ստուգել այն տվյալները, որոնցով աշխատում է հարցումը (արժեքներ, ընտրված տվյալների տեսակներ)
  2. իրականացնել այս տվյալների պատշաճ ինդեքսավորում
  3. ստուգեք աղյուսակների միջև միացման պայմանների ճիշտությունը

Հաջորդ օպտիմալացման կրկնությունը բացահայտում է.

  1. խնդրանքի հիմքում և սահմանում է հարցման հիմնական զտիչը
  2. կրկնելով նմանատիպ հարցումների բլոկները և վերլուծելով պայմանների խաչմերուկը
  3. SSMS-ում կամ այլ GUI-ի համար SQL Server օպտիմիզացնում է ինքն իրեն SQL հարցում (Տվյալների միջանկյալ պահեստի տեղաբաշխում, արդյունքում ստացված հարցումը օգտագործելով այս պահեստը (կարող է լինել մի քանի))
  4. վերջին փուլում՝ հիմք ընդունելով ստացվածը SQL հարցում, կառույցը վերակառուցվում է LINQ հարցում

Ստացվածը LINQ հարցում կառուցվածքով պետք է նույնական դառնա բացահայտված օպտիմալին SQL հարցում 3-րդ կետից.

Շնորհակալագրեր

Շատ շնորհակալություն գործընկերներին jobgemws и alex_ozr ընկերությունից Fortis այս նյութի պատրաստման հարցում օգնության համար:

Source: www.habr.com

Добавить комментарий