2

だからここに私のスキーマがあります(与えるか取るか):

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 sys 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 sys 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 sys 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 sys 0.078001

これで、「+」を追加すると時間が変わる理由がわかりましたが、AssetId の変更と矛盾するのはなぜですか? これらの MIN クエリ用に作成する必要がある他のインデックスはありますか? Events テーブルには 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;
4

1 に答える 1

1

ブラノン、

AssetIDの変更による時差について: おそらくすでにこれを試しましたが、各クエリを連続して数回実行しましたか?オペレーティングシステムとsqliteの両方のメモリキャッシュにより、セッション内での最初の実行よりも2番目のクエリがはるかに高速になることがよくあります。特定のクエリを4回続けて実行し、2回目から4回目の実行のタイミングがより一貫しているかどうかを確認します。

「+」の使用について (知らない人のために、「+」が付いたフィールドの前にあるSELECT内で、クエリでそのフィールドのインデックスを使用しないようにヒントをsqliteに与えます。sqliteが最適化されている場合、クエリで結果が失われる可能性がありますそのインデックスにのみデータを保持するためのストレージ。これは非推奨であると思われます。)ANALYZEコマンドを実行しましたか?それは決定を下すときにsqliteオプティマイザーをかなり助けます。
http://sqlite.org/lang_analyze.html スキーマが安定し、テーブルにデータが入力されると、実行する必要があるのは1回だけで、毎日実行する必要はありません。

INDEXED BY INDEXED BYは、作成者が通常の使用を推奨しない機能ですが、評価に役立つ場合があります。 http://www.sqlite.org/lang_indexedby.html

私はあなたが何を発見したか知りたいです、ドナルド・グリッグス、サウスカロライナ州コロンビア

于 2012-06-14T16:46:27.407 に答える