C# 大数据集多对多关系查询优化

C# 大数据集多对多关系查询优化,c#,sql,linq,entity-framework,sqlite,C#,Sql,Linq,Entity Framework,Sqlite,我有一个使用类似DDL构建的数据库(SQLite): CREATE TABLE [Player] ( [PlayerID] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, [Name] TEXT UNIQUE NULL

我有一个使用类似DDL构建的数据库(SQLite):

                                    CREATE TABLE [Player] (
                                        [PlayerID] INTEGER  PRIMARY KEY AUTOINCREMENT NOT NULL,
                                        [Name] TEXT  UNIQUE NULL
                                        );
                                    CREATE TABLE [Position] (
                                        [PlayerID] INTEGER  NOT NULL,
                                        [SingleHandID] INTEGER  NOT NULL,
                                        [Position] INTEGER  NULL,
                                        PRIMARY KEY ([PlayerID],[SingleHandID])
                                        );
                                    CREATE TABLE [SingleHand] (
                                        [SingleHandID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,
                                        [Stake] FLOAT  NULL,
                                        [Date] DATE  NULL,
                                        DataSetID INTEGER NULL
                                        [IsPreflopAllIn] BOOLEAN  NULL
                                        );

                                    CREATE UNIQUE INDEX [NameIndex] ON [Player](
                                        [Name]  ASC

                                    CREATE INDEX [DataSetIndex] ON [SingleHand](
                                    [DataSetID]  ASC
                                    );
它被映射到实体框架模型。我正在处理大数据集,每个数据集最多有1000万条记录

我的问题是,我需要找到所有特定玩家在任何给定位置(加上一些其他过滤器,如日期范围)被刺痛的手

虽然我可以非常快速地扫描数据库,但要从单个表中查找数据,例如:

//[playerIDs and selectedPos are cashed in memory]

context.Positions.Where(p => playerIDs.Contains(p.PlayerID) && selectedPos.Contains(p.Position)).Select(p => p.SingleHandID).Take(maxHands ?? 1);
//accesing both Position and SingleHand table
context.Positions.Where(p => playerIDs.Contains(p.PlayerID) && selectedPos.Contains(p.Position) && p.SingleHand.DataSetID == dataSetNumber).Select(p => p.SingleHandID).Take(maxHands ?? 1);
当我需要在表之间进行任何连接时,它开始运行得非常慢,例如:

//[playerIDs and selectedPos are cashed in memory]

context.Positions.Where(p => playerIDs.Contains(p.PlayerID) && selectedPos.Contains(p.Position)).Select(p => p.SingleHandID).Take(maxHands ?? 1);
//accesing both Position and SingleHand table
context.Positions.Where(p => playerIDs.Contains(p.PlayerID) && selectedPos.Contains(p.Position) && p.SingleHand.DataSetID == dataSetNumber).Select(p => p.SingleHandID).Take(maxHands ?? 1);
我可以使用什么巧妙的技巧、comining查询和代码(例如,使用本地缓存)来提高运行效率?我正在使用System.Data.SQLite提供程序

也许我应该在Position表中添加冗余的DataSetID,这样我就可以只对Position表进行主查询了?稍后,当我拥有所有匹配手的ID时,添加附加条件(如日期检查)应该会更快。

创建一个新索引:

CREATE INDEX [DataSetIndex2] ON [SingleHand](
    [SingleHandID] ASC,
    [DataSetID]  ASC
);
这应该会有很大帮助

您也可以尝试以下方法:

context.Positions
  .Where(p => playerIDs.Contains(p.PlayerID) && SelectedPos.Contains(p.Position))
  .Select(p => p.SingleHandID)
.Intersect(context.SingleHand
   .Where(s=>s.DataSetId==dataSetNumber)
   .Select(s=>s.SingleHandID))
.Take(maxHands ?? 1);

有太多的变量会影响您建议的超过1000万条记录的查询的性能。表行大小、SQL索引和一系列设置。对于粗略的第一步,我建议创建一个视图,在DB服务器中单独优化该视图,然后使用EF查询
NameIndex
是多余的,因为该列已经有一个
唯一的
约束。要检查查询的优化程度,将其转换为SQL并查看的输出。非常感谢:)我需要做更多的测试,但似乎使用该索引的性能是可以接受的(使用我发布的代码,在这种情况下尝试Intersect似乎会给出结果)。我还有一个问题-当我将“.OrderBy(p=>p.SingleHandID)”添加到查询中时,我可以使用分页(当用户等待执行时,为用户提供一些进度反馈),它的速度非常慢-可能我没有使用任何索引。添加以下索引是个好主意吗?索引[Position]([SingleHandID]ASC)上的[HandId]。或者,您可以将复合主键更改为将SingleHandID列为第一个键。性能的提高不会太大,因为您仍然需要查找记录以对其进行过滤,但这可能会有所帮助。