C# 大数据集多对多关系查询优化
我有一个使用类似DDL构建的数据库(SQLite):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
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列为第一个键。性能的提高不会太大,因为您仍然需要查找记录以对其进行过滤,但这可能会有所帮助。