sqlite性能问题:每个表一个索引有点痛苦

sqlite性能问题:每个表一个索引有点痛苦,sql,performance,sqlite,indexing,Sql,Performance,Sqlite,Indexing,这是我的模式,不给即取: cmds.Add(@"CREATE TABLE [Services] ([Id] INTEGER PRIMARY KEY, [AssetId] INTEGER NULL, [Name] TEXT NOT NULL)"); cmds.Add(@"CREATE INDEX [IX_Services_AssetId] ON [Services] ([AssetId])"); cmds.Add(@"CREATE INDEX [IX_Services_Name] ON [Serv

这是我的模式,不给即取:

cmds.Add(@"CREATE TABLE [Services] ([Id] INTEGER PRIMARY KEY, [AssetId] INTEGER NULL, [Name] TEXT NOT NULL)");
cmds.Add(@"CREATE INDEX [IX_Services_AssetId] ON [Services] ([AssetId])");
cmds.Add(@"CREATE INDEX [IX_Services_Name] ON [Services] ([Name])");

cmds.Add(@"CREATE TABLE [Telemetry] ([Id] INTEGER PRIMARY KEY, [ServiceId] INTEGER NULL, [Name] TEXT NOT NULL)");
cmds.Add(@"CREATE INDEX [IX_Telemetry_ServiceId] ON [Telemetry] ([ServiceId])");
cmds.Add(@"CREATE INDEX [IX_Telemetry_Name] ON [Telemetry] ([Name])");

cmds.Add(@"CREATE TABLE [Events] ([Id] INTEGER PRIMARY KEY, [TelemetryId] INTEGER NOT NULL, [TimestampTicks] INTEGER NOT NULL, [Value] TEXT NOT NULL)");
cmds.Add(@"CREATE INDEX [IX_Events_TelemetryId] ON [Events] ([TelemetryId])");
cmds.Add(@"CREATE INDEX [IX_Events_TimestampTicks] ON [Events] ([TimestampTicks])");
下面是我的查询及其奇怪的计时器结果:

sqlite> SELECT MIN(e.TimestampTicks) FROM Events e INNER JOIN Telemetry ss ON ss.ID = e.TelemetryID INNER JOIN Services s ON s.ID = ss.ServiceID WHERE s.AssetID = 1;
634678974004420000 CPU时间:用户0.296402系统0.374402

sqlite> SELECT MIN(e.TimestampTicks) FROM Events e INNER JOIN Telemetry ss ON ss.ID = e.TelemetryID INNER JOIN Services s ON s.ID = ss.ServiceID WHERE s.AssetID = 2;
634691940264680000 CPU时间:用户0.062400系统0.124801

sqlite> SELECT MIN(e.TimestampTicks) FROM Events e INNER JOIN Telemetry ss ON ss.ID = +e.TelemetryID INNER JOIN Services s ON s.ID = ss.ServiceID WHERE s.AssetID = 1;
634678974004420000 CPU时间:用户0.000000系统0.000000

sqlite> SELECT MIN(e.TimestampTicks) FROM Events e INNER JOIN Telemetry ss ON ss.ID = +e.TelemetryID INNER JOIN Services s ON s.ID = ss.ServiceID WHERE s.AssetID = 2;
634691940264680000 CPU时间:用户0.265202系统0.078001

现在我可以理解为什么添加“+”可能会更改时间,但为什么它与AssetId更改不一致?我是否应该为这些MIN查询创建其他索引?事件表中有900000行

首先用“+”查询计划:

0|0|0|SEARCH TABLE Events AS e USING INDEX IX_Events_TimestampTicks (~1 rows)
0|1|1|SEARCH TABLE Telemetry AS ss USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0|2|2|SEARCH TABLE Services AS s USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)

0|0|2|SEARCH TABLE Services AS s USING COVERING INDEX IX_Services_AssetId (AssetId=?) (~1 rows)
0|1|1|SEARCH TABLE Telemetry AS ss USING COVERING INDEX IX_Telemetry_ServiceId (ServiceId=?) (~1 rows)
0|2|0|SEARCH TABLE Events AS e USING INDEX IX_Events_TelemetryId (TelemetryId=?) (~1 rows)
编辑:总之,对于上面的表,如果这些是唯一要执行的查询,您将创建哪些索引:

SELECT MIN/MAX(e.TimestampTicks) FROM Events e INNER JOIN Telemetry t ON t.ID = e.TelemetryID INNER JOIN Services s ON s.ID = t.ServiceID WHERE s.AssetID = @AssetId;

SELECT e1.* FROM Events e1 INNER JOIN Telemetry t1 ON t1.Id = e1.TelemetryId INNER JOIN Services s1 ON s1.Id = t1.ServiceId WHERE t1.Name = @TelemetryName AND s1.Name = @ServiceName;

SELECT * FROM Events e INNER JOIN Telemetry t ON t.Id = e.TelemetryId INNER JOIN Services s ON s.Id = t.ServiceId WHERE s.AssetId = @AssetId AND e.TimestampTicks >= @StartTimeTicks ORDER BY e.TimestampTicks LIMIT 1000;

SELECT e.Id, e.TelemetryId, e.TimestampTicks, e.Value FROM (
                SELECT e2.Id AS [Id], MAX(e2.TimestampTicks) as [TimestampTicks]
                                FROM Events e2 INNER JOIN Telemetry t ON t.Id = e2.TelemetryId INNER JOIN Services s ON s.Id = t.ServiceId
                                WHERE s.AssetId = @AssetId AND e2.TimestampTicks <= @StartTimeTicks 
                                GROUP BY e2.TelemetryId) AS grp
INNER JOIN Events e ON grp.Id = e.Id;
布兰农

关于资产变动的时差: 也许您已经尝试过了,但是您是否已经连续多次运行了每个查询?操作系统和sqlite的内存缓存通常会使第二次查询比会话中的第一次运行快得多。我会连续四次运行给定的查询,看看第二次到第四次运行的时间是否更一致

关于使用+ 对于那些可能不知道的人,在带有+的字段前面的SELECT中,会提示sqlite不要在查询中使用该字段的索引。如果sqlite优化了存储以仅将数据保留在该索引中,则可能会导致查询丢失结果。怀疑这是不推荐的。 您是否运行了ANALYZE命令?它在决策时对sqlite优化器有很大帮助。 一旦您的模式稳定并填充了表,您可能只需要运行一次,而无需每天运行一次

索引 编入索引是作者不鼓励用于典型用途的功能,但您可能会发现它对您的评估很有帮助。

我很想知道你发现了什么,
Donald Griggs,Columbia SC USA

我已经连续多次运行查询。我还使用了分析功能。我已经查看了“按索引”功能,但还没有尝试过。它与“+”有何不同?我真正需要的是根据某个项目接近或远离的概率动态切换索引使用,这可以通过比较具有特定FK的行数与表中所有行数来确定。我已经转到使用索引方式。“+”处理似乎是不确定的。