【发布时间】: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 的输出。
标签: c# sql linq entity-framework sqlite