БД SQLite: создайте оператор SQL с LINQ, который использует одну и ту же таблицу дважды, но без CROSS JOIN - PullRequest
1 голос
/ 27 января 2020

Как мне создать оператор SQL, как показано ниже с LINQ. Основная проблема - вторая строка оператора SQL. Строки 3 и 4 не являются проблемой.

SELECT node.Label
FROM MpttModel AS node, MpttModel AS parent
WHERE node.Lft >= parent.Lft AND node.Lft <= parent.Rght
AND parent.Id IN ( X'8761620FA1B0DD4AB852324AACE0FEF3' , X'45E88A219EE0A347B51DFD8A6417C806' )

Я выяснил, что следующий оператор LINQ создает оператор SQL с предложением CROSS JOIN:

from node in DbSet
from parent in DbSet
where node.Lft >= parent.Lft && node.Lft <= parent.Rght && ids.Contains(parent.Id)
select node

SELECT 
[Extent1].*
FROM     [MpttModel] AS [Extent1] CROSS JOIN [MpttModel] AS [Extent2]
WHERE (([Extent1].[Discriminator] = 'WorkEstimationStructure') AND ([Extent2].[Discriminator] = 'WorkEstimationStructure')) AND ((([Extent1].[Lft] >= [Extent2].[Lft]) AND ([Extent1].[Lft] <= [Extent2].[Rght])) 
AND ([Extent2].[Id] IN ( X'8761620FA1B0DD4AB852324AACE0FEF3' , X'45E88A219EE0A347B51DFD8A6417C806' , X'D4B4A84AE2C8D346A6EB4BE649009353' , X'79791D780A820D47A6C643049DD2EDAC' , X'6D87228654D58047ACB0C9883BBEC18F' , X'A92CBE900AFE5F4E8601A3138D5868F2' , X'8033A7D64861FD48B7AF10DB3BC94317' , X'78EF4038766C784C81C80B8904B5735A' , X'37251B4BAC5D2A42A1F4C22145C03E1B' , X'49CD6E59D0E9E64B8B672A497C408B99' , X'C237D7A22A75714BB0D9EA7F6A3771AF' , X'F13F9BCC255A7C4DB65371A3FB35F6AD' , X'6A0B11D63C954E4F9FC4F50E034F3848' , X'48A06CE22403F84382C8769FBDCAA776' , X'F212153580158741AFF56513FEA97EB7' , X'8A21DB4B1573454E8A0AB53799508887' , X'DD15497B20BBFC4692BA263D8BE54018' , X'621922914C5F4D488AEF671CE1F3B64F' , X'5091809E6C708B48AE1F73A8773658B3' , X'AF0628D49152404FA7B7C50AE249378A' , X'62442AD65175F54E8F93D11579A3F4F4' , X'951E0010A8E4C249B4911F9DA2EE3DC8' , X'43F3B828F1D1FD4282059664973E3CDB' , X'D6365B468A01D34EA0ACF0FFC4626D02' , X'8F4D77A09686C5428234C071916AF5D5' , X'1C34C9B2B8E1404BB37F3CBB61B7E52A' , X'68F96BB653267B4AB1F96F0D55144B2B' , X'764F15B9C92C9B4CA83C30A7A95D65A0' , X'00000000000000000000000000004421' , X'00000000000000000000000000005633' , X'6070CA1A4B752B43BDEB4B4485648D60' , X'381CDA5510E81146B5AE62B6845A386B' , X'D20ED55AF5229141915156CFC40BDB58' , X'0FCE62A75BD86F4794EBFCF191552A31' , X'ABD4F4B7D6185141888AF4D99CBBEE57' , X'BC27D6D8BE13704BAFECA931763E3E09' , X'9B2C09FEDAEA054ABB7AA848F03C88FD' , X'89A6A808AF58EA40B206D3F20CFAB87D' , X'7BA1431A374C9749A6EAA1AC9C54C976' , X'DA48285B4FD885499E4897BBAA05D5B3' , X'8081F1BE856DF447AC36142FFF07C8D1' , X'7A2BDCC438EFD3468DE129BD40D11826' , X'F99832C5398C25499520CB99210B6E15' , X'8A34A4D676337D41879B435C8FC9393E' , X'2B29F4CDB6C06147812E70205A641B3E' , X'19228B5D9642C14C905DD225AD8F00AD' , X'63061BC02F37404E8F841A600AEAFDBE' , X'79E8AC96B98C914490557327FE8AD99F' , X'185C5BB3FC2D7E4BB81DFB555DE4012E' , X'82B0F0107AA4394BBD9E2525E5DCAF9D' , X'4E240A379E2305438DFFC4AF00CAB274' , X'FADFDC43A4FB4B459B08DBD83C5B4496' , X'DE02C14D47254346BB8734BF028BBDDC' , X'2E4A5A6A67100D4A8E8C35998C36AA91' , X'12A71EAFE79BBF4DADB9BAFA45DA1A4E' , X'3C22F7AF7B34A1449DEDBAE6CE4EA5D4' , X'8DBE21EB670C5E40AAB54F3F1913B32B' , X'9857BEEE9353194281A9FC257ED7994F' , X'D0EC2B3F1A676244ADD6C82AABE34D84' , X'15869193081463498E00C428A14711AF' , X'2DD95FBD59069549A6F25A3B47974DAE' , X'CCFC9753A321B146B584CB13F4A26745' , X'9743F50C3C2F08428258B181D407391E' , X'1DACD568C2E88F49BD5C980E0EFCDF33' , X'69BFBDC788B77742A7BF60F6E7992CF9' , X'0828AE10A5058B4991598E58A5B27738' , X'B159FABDB2E05945BD45D3F7E16FE60A' , X'D34E4706E86AEA4FA7976A477C4A486D' , X'2CF9198F2FE33A40B3E52617D6C33641' , X'816F44DB755FF647A8BB27F343D596DF' , X'ABE5A80D135D604CB9063876CBD1193B' , X'C523FA22DF508F4B936ACB519C8EDA4B' , X'87D03027E667D44BB9EEAF8BA0253E05' , X'4B2AAC361F376D498361C2E760745A01' , X'64455E4705D74448B067058320091871' , X'EF86315366DB9540B09CEB4F8D985D13' , X'0F0EEF5CB653244AAADDBDDC78AB655A' , X'E2E4907477F39A46AE32044E8C2C42C6' , X'5FF7A27C872895479868445CA7D73237' , X'106CB4897B8A0B4AB2EABC61503BCB0E' , X'2CD76B9C3C4AE042AD7B12E8F4D27469' , X'B9491AB25CC74C4CADF312B6F7FEA384' , X'0B55BEBEE02A804A9B2745855222FDEE' , X'1CC879BFC5ED3743B658E45EDEA9ECC6' , X'E29DDAE4E282E1469835802FC781A049' , X'1662D9E7A56F2E45A961C03E3AD49022' , X'95E0BFF84497A84886978173FC576A69' , X'035CF8001385C64BAA4C0666218B36A2' , X'B211CB09DC354E42BFF44BDCA86D0E34' , X'618083225CC69A42800F7C9DFF5C5081' , X'F250803712AEC148A2443F5AE3ED89DD' , X'FD83B63D332E334193043F18DF2F7665' , X'4AFE5C40C7F36947A7D0D9B853A975DE' , X'3EC8844DAD9D214BA1377A3742AEF267' , X'AF868F584C84414E9250AF2696032FE7' , X'8A27895FB4B17643AC836D62EA2B35E8' , X'8015A6688AF73D4ABEC7EDCCBC62FDCA' , X'AB2FFB71D7690F4EA0494B4AD9248D2D' , X'BEAB2E815F58F24AB7037B435E88BE67' , X'BC4267872ACAE841BC1F99495FDCBD67' , X'3C3032BAFBAC0745B977984238824F24' , X'529CAFBDE23120418B46BEC459445750' , X'9D7665C2286ABA419F464F657A17CFCE' , X'8EE875D745F5244F934B967FFB08BB94' , X'014336DF050FC643B22EEA2CAD4007BA' , X'2BD6A2F9C532E246AF5D52BD2977CC2C' , X'A5F6952854E8414EAB5243866D51299C' , X'7B84D38E009DE543AFA57551020784E4' , X'E6F711AB04ECD9489F6841990ADB588B' )))

Выполнение Это SQL утверждение занимает около 50 секунд в моей базе данных SQLite! Если я заменю предложение CROSS JOIN символом «,», то почти то же самое выражение SQL займет меньше секунды (~ 750 мс). В чем здесь проблема?

Оптимизировано SQL Оператор без предложения CROSS JOIN:

SELECT 
[Extent1].*
FROM     [MpttModel] AS [Extent1], [MpttModel] AS [Extent2]
WHERE (([Extent1].[Discriminator] = 'WorkEstimationStructure') AND ([Extent2].[Discriminator] = 'WorkEstimationStructure')) AND ((([Extent1].[Lft] >= [Extent2].[Lft]) AND ([Extent1].[Lft] <= [Extent2].[Rght])) 
AND ([Extent2].[Id] IN ( X'8761620FA1B0DD4AB852324AACE0FEF3' , X'45E88A219EE0A347B51DFD8A6417C806' , X'D4B4A84AE2C8D346A6EB4BE649009353' , X'79791D780A820D47A6C643049DD2EDAC' , X'6D87228654D58047ACB0C9883BBEC18F' , X'A92CBE900AFE5F4E8601A3138D5868F2' , X'8033A7D64861FD48B7AF10DB3BC94317' , X'78EF4038766C784C81C80B8904B5735A' , X'37251B4BAC5D2A42A1F4C22145C03E1B' , X'49CD6E59D0E9E64B8B672A497C408B99' , X'C237D7A22A75714BB0D9EA7F6A3771AF' , X'F13F9BCC255A7C4DB65371A3FB35F6AD' , X'6A0B11D63C954E4F9FC4F50E034F3848' , X'48A06CE22403F84382C8769FBDCAA776' , X'F212153580158741AFF56513FEA97EB7' , X'8A21DB4B1573454E8A0AB53799508887' , X'DD15497B20BBFC4692BA263D8BE54018' , X'621922914C5F4D488AEF671CE1F3B64F' , X'5091809E6C708B48AE1F73A8773658B3' , X'AF0628D49152404FA7B7C50AE249378A' , X'62442AD65175F54E8F93D11579A3F4F4' , X'951E0010A8E4C249B4911F9DA2EE3DC8' , X'43F3B828F1D1FD4282059664973E3CDB' , X'D6365B468A01D34EA0ACF0FFC4626D02' , X'8F4D77A09686C5428234C071916AF5D5' , X'1C34C9B2B8E1404BB37F3CBB61B7E52A' , X'68F96BB653267B4AB1F96F0D55144B2B' , X'764F15B9C92C9B4CA83C30A7A95D65A0' , X'00000000000000000000000000004421' , X'00000000000000000000000000005633' , X'6070CA1A4B752B43BDEB4B4485648D60' , X'381CDA5510E81146B5AE62B6845A386B' , X'D20ED55AF5229141915156CFC40BDB58' , X'0FCE62A75BD86F4794EBFCF191552A31' , X'ABD4F4B7D6185141888AF4D99CBBEE57' , X'BC27D6D8BE13704BAFECA931763E3E09' , X'9B2C09FEDAEA054ABB7AA848F03C88FD' , X'89A6A808AF58EA40B206D3F20CFAB87D' , X'7BA1431A374C9749A6EAA1AC9C54C976' , X'DA48285B4FD885499E4897BBAA05D5B3' , X'8081F1BE856DF447AC36142FFF07C8D1' , X'7A2BDCC438EFD3468DE129BD40D11826' , X'F99832C5398C25499520CB99210B6E15' , X'8A34A4D676337D41879B435C8FC9393E' , X'2B29F4CDB6C06147812E70205A641B3E' , X'19228B5D9642C14C905DD225AD8F00AD' , X'63061BC02F37404E8F841A600AEAFDBE' , X'79E8AC96B98C914490557327FE8AD99F' , X'185C5BB3FC2D7E4BB81DFB555DE4012E' , X'82B0F0107AA4394BBD9E2525E5DCAF9D' , X'4E240A379E2305438DFFC4AF00CAB274' , X'FADFDC43A4FB4B459B08DBD83C5B4496' , X'DE02C14D47254346BB8734BF028BBDDC' , X'2E4A5A6A67100D4A8E8C35998C36AA91' , X'12A71EAFE79BBF4DADB9BAFA45DA1A4E' , X'3C22F7AF7B34A1449DEDBAE6CE4EA5D4' , X'8DBE21EB670C5E40AAB54F3F1913B32B' , X'9857BEEE9353194281A9FC257ED7994F' , X'D0EC2B3F1A676244ADD6C82AABE34D84' , X'15869193081463498E00C428A14711AF' , X'2DD95FBD59069549A6F25A3B47974DAE' , X'CCFC9753A321B146B584CB13F4A26745' , X'9743F50C3C2F08428258B181D407391E' , X'1DACD568C2E88F49BD5C980E0EFCDF33' , X'69BFBDC788B77742A7BF60F6E7992CF9' , X'0828AE10A5058B4991598E58A5B27738' , X'B159FABDB2E05945BD45D3F7E16FE60A' , X'D34E4706E86AEA4FA7976A477C4A486D' , X'2CF9198F2FE33A40B3E52617D6C33641' , X'816F44DB755FF647A8BB27F343D596DF' , X'ABE5A80D135D604CB9063876CBD1193B' , X'C523FA22DF508F4B936ACB519C8EDA4B' , X'87D03027E667D44BB9EEAF8BA0253E05' , X'4B2AAC361F376D498361C2E760745A01' , X'64455E4705D74448B067058320091871' , X'EF86315366DB9540B09CEB4F8D985D13' , X'0F0EEF5CB653244AAADDBDDC78AB655A' , X'E2E4907477F39A46AE32044E8C2C42C6' , X'5FF7A27C872895479868445CA7D73237' , X'106CB4897B8A0B4AB2EABC61503BCB0E' , X'2CD76B9C3C4AE042AD7B12E8F4D27469' , X'B9491AB25CC74C4CADF312B6F7FEA384' , X'0B55BEBEE02A804A9B2745855222FDEE' , X'1CC879BFC5ED3743B658E45EDEA9ECC6' , X'E29DDAE4E282E1469835802FC781A049' , X'1662D9E7A56F2E45A961C03E3AD49022' , X'95E0BFF84497A84886978173FC576A69' , X'035CF8001385C64BAA4C0666218B36A2' , X'B211CB09DC354E42BFF44BDCA86D0E34' , X'618083225CC69A42800F7C9DFF5C5081' , X'F250803712AEC148A2443F5AE3ED89DD' , X'FD83B63D332E334193043F18DF2F7665' , X'4AFE5C40C7F36947A7D0D9B853A975DE' , X'3EC8844DAD9D214BA1377A3742AEF267' , X'AF868F584C84414E9250AF2696032FE7' , X'8A27895FB4B17643AC836D62EA2B35E8' , X'8015A6688AF73D4ABEC7EDCCBC62FDCA' , X'AB2FFB71D7690F4EA0494B4AD9248D2D' , X'BEAB2E815F58F24AB7037B435E88BE67' , X'BC4267872ACAE841BC1F99495FDCBD67' , X'3C3032BAFBAC0745B977984238824F24' , X'529CAFBDE23120418B46BEC459445750' , X'9D7665C2286ABA419F464F657A17CFCE' , X'8EE875D745F5244F934B967FFB08BB94' , X'014336DF050FC643B22EEA2CAD4007BA' , X'2BD6A2F9C532E246AF5D52BD2977CC2C' , X'A5F6952854E8414EAB5243866D51299C' , X'7B84D38E009DE543AFA57551020784E4' , X'E6F711AB04ECD9489F6841990ADB588B' )))

Моя таблица базы данных MPTTModel содержит около 10 000 строк.

Ответы [ 3 ]

1 голос
/ 27 января 2020

Метод 1:

Если в таблице базы данных MpttModel отсутствует самоссылающийся столбец, используйте обычное перекрестное соединение, как показано ниже:

var ids = new List<string> { "8761620FA1B0DD4AB852324AACE0FEF3", "45E88A219EE0A347B51DFD8A6417C806" };

var results = db.MpttModels.SelectMany(n => db.MpttModels.Select(p => new
{
    n, p
})).Where(a => ids.Contains(a.p.Id) && a.n.Lft >= a.p.Lft && a.n.Lft <= a.p.Right);

ИЛИ

var ids = new List<string> { "8761620FA1B0DD4AB852324AACE0FEF3", "45E88A219EE0A347B51DFD8A6417C806" };
var resultsViaLinq = db.MpttModels.SelectMany(node => db.MpttModels, (node, parent) => new {node, parent})
    .Where(@t =>
        @t.node.Lft >= @t.parent.Lft && @t.node.Lft <= @t.parent.Right && ids.Contains(@t.parent.Id))
    .Select(@t => new {@t.node.Label});

ИЛИ

var ids = new List<string> { "8761620FA1B0DD4AB852324AACE0FEF3", "45E88A219EE0A347B51DFD8A6417C806" };
var resultsViaLinq = from node in db.MpttModels
                    from parent in db.MpttModels
                        where node.Lft >= parent.Lft && node.Lft <= parent.Right && ids.Contains(parent.Id)
                    select new
                    {
                        node.Label
                    };

Метод 2:

Вы можете изменить таблицу базы данных с родительским столбцом и изменить модель c#, как показано ниже, для представления отношений родитель-ребенок:

public class MpttModel
{
    public int MpttModelId { get; set; }

    public int? ParentId { get; set; }

    [ForeignKey("ParentId")]
    public virtual MpttModel Parent { get; set; }

    public virtual ICollection<MpttModel> Children { get; set; }
}

То же самое можно сделать через свободный API.

0 голосов
/ 28 января 2020

Я мог решить проблему производительности с помощью предложения CROSS JOIN. Проблема производительности возникает только в базах данных SQLite . MS SQL -Server не затрагивается. Как описано в документации SQLite, 7.3. Ручное управление планами запросов С помощью CROSS JOIN проблему производительности можно решить, изменив порядок используемых таблиц.

Оператор LINQ ранее (с проблемами производительности). Запрос занял около 50 секунд:

from node in DbSet
from parent in DbSet
where node.Lft >= parent.Lft && node.Lft <= parent.Rght && ids.Contains(parent.Id)
select node

Новый оператор LINQ, который решил проблему. Запрос занимает менее 1 секунды:

from parent in DbSet
from node in DbSet
where node.Lft >= parent.Lft && node.Lft <= parent.Rght && ids.Contains(parent.Id)
select node
0 голосов
/ 27 января 2020

Запросы в сущности c# должны выглядеть точно так же, как SQL Запросы к серверу. Вы можете использовать один код Где, как показано ниже:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication152
{
    class Program
    {
        static void Main(string[] args)
        {
            DataBase db = new DataBase();

            string[] labels = db.MpttModel.Where(x => (x.Lft.CompareTo(x.Rght) <= 0) && (x.Id.CompareTo("8761620FA1B0DD4AB852324AACE0FEF3") >= 0) && (x.Id.CompareTo("45E88A219EE0A347B51DFD8A6417C806") <=0)).Select(x => x.Label).ToArray();
        }
    }
    public class DataBase
    {
        public List<MpttModel> MpttModel { get; set; } 
    }
    public class MpttModel
    {
        public string Label { get; set; }
        public string Lft { get; set; }
        public string Rght { get; set; }
        public string Id { get; set; }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...