优化大数据集上的多对多关系查询
Posted
技术标签:
【中文标题】优化大数据集上的多对多关系查询【英文标题】:Optimizing query with many-to-many relationship on big data set 【发布时间】:2013-07-03 16:39:15 【问题描述】:我有一个使用类似 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);
我可以提取什么巧妙的技巧、合并查询和代码(例如,使用本地缓存),以使其运行效率最高?我正在使用 System.Data.SQLite 提供程序。
也许我应该在 Position 表中添加多余的 DataSetID,然后我只能在 Position 表上进行主要查询?稍后,当我将获得所有匹配手的 ID 时,添加附加条件(如日期检查)应该会更快
【问题讨论】:
有太多变量会影响您建议的超过 10m 记录的查询的性能。表行大小、SQL 索引和一堆设置。对于粗略的第一次拍摄,我建议创建一个视图,在您的数据库服务器中单独优化它,然后使用 EF 来查询它NameIndex
是多余的,因为该列已经具有 UNIQUE
约束。
要检查查询的优化程度,将其转换为 SQL 并查看 EXPLAIN QUERY PLAN 的输出。
【参考方案1】:
创建新索引:
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);
【讨论】:
非常感谢 :) 我需要做更多的测试,但看起来,使用该索引,性能是可以接受的(使用我发布的代码,尝试你的 Intersect 似乎给出了磨损的结果这个案例)。我还有一个问题 - 当我将“.OrderBy(p => p.SingleHandID)”添加到查询中时,我可以使用使用分页(在用户等待执行此操作时向用户提供有关进度的一些反馈)它速度非常慢 - 可能我没有使用任何索引。添加以下索引是个好主意吗? INDEX [HandIdIndex] ON [Position]( [SingleHandID] ASC ) 可能。或者您可以更改复合主键以将 SingleHandID 列为第一个键。性能提升不会那么大,因为您仍然需要查找记录来过滤它,但它可能会有所帮助。以上是关于优化大数据集上的多对多关系查询的主要内容,如果未能解决你的问题,请参考以下文章