【发布时间】:2013-03-06 22:00:17
【问题描述】:
Sqlite 有一个限制,即每次查询只能使用一个索引。这个限制目前正在困扰着我,但我需要 Sqlite,因为我不知道有任何其他本地数据库引擎可以竞争插入速度(尽管我愿意接受建议)。
我有一个包含一百万到一千万行的简单表格(以及其他表格):
CREATE TABLE [Events] (
[Id] INTEGER PRIMARY KEY,
[TelemetryId] INTEGER NOT NULL,
[TimestampTicks] INTEGER NOT NULL,
[Value] TEXT NOT NULL)
查看我的数据,我有大约 2000 个唯一 TelemetryId 值和每个唯一 TelemetryId 大约 25000 行。我一直在使用这个索引:
CREATE INDEX [IX_Events_TimestampTicks_TelemetryId]
ON [Events] ([TimestampTicks], [TelemetryId])
但是,该索引在我没有传入 TimestampTicks 约束的查询中失败(显然)。该索引是在我尝试了 TimestampTicks 和 TelemetryId 上的单个索引之后。根据我的测试,甚至在运行ANALYZE 之后,Sqlite 只会在引用 TelemetryId 时使用索引——这在我限制为时间戳范围的查询中是错误的。如果我颠倒组合索引中列的顺序,我之前快速的查询就会变慢。
这是我的查询的完整列表。你能看到一个适用于所有这些的索引方案吗?
INSERT INTO Events (TelemetryId, TimestampTicks, Value)
VALUES(@TelemetryId, @TimestampTicks, @Value); SELECT last_insert_rowid()
SELECT * FROM Events e
INNER JOIN Telemetry ss ON ss.Id = e.TelemetryId
INNER JOIN Services s ON s.Id = ss.ServiceId
WHERE s.AssetId = @AssetId AND e.TimestampTicks >= @StartTime
ORDER BY e.TimestampTicks LIMIT 10000
SELECT * FROM Events e
WHERE e.TimestampTicks >= @StartTime
ORDER BY e.TimestampTicks LIMIT 10000
SELECT * FROM Events
WHERE TelemetryId = @TelemetryId AND TimestampTicks <= @TimestampTicks
ORDER BY TimestampTicks DESC LIMIT 1
SELECT MIN(TimestampTicks) FROM Events
SELECT MAX(TimestampTicks) FROM Events
SELECT COUNT(*) FROM Events
SELECT TimestampTicks, [Value] FROM Events
WHERE TelemetryId = @TelemetryId
SELECT Id FROM Events
WHERE TelemetryId = @TelemetryId LIMIT 2
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 = @AssetId
SELECT MAX(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 = @AssetId
SELECT * FROM Events
WHERE TimestampTicks <= @TimestampTicks AND TelemetryId = @TelemetryId
ORDER BY TimestampTicks DESC LIMIT 1
SELECT e.Id, e.TelemetryId, e.TimestampTicks, e.Value
FROM (SELECT e2.Id AS [Id], MIN(e2.TimestampTicks) as [TimestampTicks]
FROM Events e2 WHERE e2.TimestampTicks
BETWEEN @Min AND @Max AND e2.TelemetryId in @TelemetryIds
GROUP BY e2.TelemetryId) AS grp
INNER JOIN Events e ON grp.Id = e.Id
【问题讨论】:
-
我建议在 AssetID、TelemetryID 和 TimeStampTicks 上使用简单的非复合索引。
标签: sql sqlite query-optimization database-indexes