Sqlite には、クエリごとに 1 つのインデックスしか使用しないという制限があります。現時点ではその制限に悩まされていますが、挿入速度を競うことができる他のローカル DB エンジンを認識していないため、Sqlite が必要です (ただし、提案は受け付けています)。
100万から1000万行のこの単純なテーブル(とりわけ)があります:
CREATE TABLE [Events] (
[Id] INTEGER PRIMARY KEY,
[TelemetryId] INTEGER NOT NULL,
[TimestampTicks] INTEGER NOT NULL,
[Value] TEXT NOT NULL)
私のデータを見ると、一意の TelemetryId 値が約 2000 あり、一意の TelemetryId ごとに約 25000 行あります。私はこのインデックスを使用しています:
CREATE INDEX [IX_Events_TimestampTicks_TelemetryId]
ON [Events] ([TimestampTicks], [TelemetryId])
ただし、そのインデックスは、(明らかに) TimestampTicks 制約を渡さないクエリで失敗します。そのインデックスは、TimestampTicks と TelemetryId で個々のインデックスを試行した後のものです。私のテストから、そして を実行した後でもANALYZE
、Sqlite は TelemetryId が参照されるたびにそのインデックスしか使用しませんでした。これは、Timestamp 範囲に制限しているクエリでは間違っています。コンボ インデックスの列の順序を逆にすると、以前は高速だったクエリが遅くなります。
これが私のクエリの完全なリストです。それらすべてで機能する索引付けスキームがわかりますか?
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