3

クエリにORDERBYステートメントを追加すると、非常に遅くなります。

ORDERBYを使用しないクエリは次のとおりです。

SELECT ClientIpAddress, Agentstring, Count(ClientIpAddress) AS Count FROM LogEntries
WHERE SiteIisId = 3 AND DateTime >= '13-09-2012 00:00:00'
GROUP BY ClientIpAddress, Agentstring
LIMIT 5

ET:1ms

そして今、ORDER BYで:

SELECT ClientIpAddress, Agentstring, Count(ClientIpAddress) AS Count FROM LogEntries
WHERE SiteIisId = 3 AND DateTime >= '13-09-2012 00:00:00'
GROUP BY ClientIpAddress, Agentstring
ORDER BY Count DESC
LIMIT 5

ET:294ミリ秒

クエリしているテーブルには1.380.855行が含まれています。

これが私が使用しているインデックスです:

CREATE INDEX "LogEntries_MostActiveClients" ON "LogEntries" ("ClientIpAddress" ASC, "Agentstring" ASC, "SiteIisId" ASC, "DateTime" DESC)

EXPLAIN QUERY PLANSqliteを使用すると、インデックスを使用してテーブルをスキャンし、OrderByに使用していることがわかりますTEMB B-TREE

どうすればこの問題を克服できますか?明らかに、インデックスを作成することはできませCountん。どうすればよいですか?

どうもありがとう!

4

2 に答える 2

1

結果セットをステップスルーするとき、SQLiteはその場でできるだけ多くの値を計算しようとします。

したがって、最初のクエリでは、SQLiteはテーブル内のすべてのアドレス/エージェント値をグループ化する必要はありません。インデックスを介して最初の5つのClientIpAddress/組み合わせのレコードを読み取るとすぐに停止できます。Agentstring

2番目のクエリでは、これは不可能です。すべてのアドレス/エージェントグループを完全に計算してから、並べ替えて最初の5つのグループを選択する必要があります。

並べ替える一時的な結果のレコードはすでにキャッシュにあり、元のテーブルのデータよりも小さいため、ほとんどの時間は並べ替えではなくグループ化に費やされていると思います。

並べ替えが問題であり、最大5つのカウントがどれだけ大きくなるかを見積もった場合は、HAVING "Count" >= some_limit句を追加して、並べ替えるレコードの数を減らすことができます。

グループ化を回避するためにできることは何もありません。試すことができるのは、次のような一般的な最適化で小さな改善を取得することだけです。

もう1つの方法は、このクエリの値を事前に計算することです。とは別のテーブルを用意しCount、ログエントリを追加するたびにそれを更新します。これにより、これらの更新が遅くなり、タイムスタンプに使用する粒度を決定する必要があります。

于 2012-10-14T15:11:36.487 に答える
0

ここにあるSQLiteの融合を使用してアプリケーションをテストします。

リチャードヒップは最近発表しました:

最近、SQLiteのクエリオプティマイザにいくつかの重要な機能拡張を行いました。特に、最新のコードは、インデックスとスキャン順序を注意深く選択し、並べ替えを行わなくても、ORDERBY句がいつ満たされるかをより適切に認識します。この最適化により、結果セットが大きいクエリのパフォーマンスが大幅に向上する可能性があります。

メールスレッドはこちらです。

于 2012-10-14T03:21:34.913 に答える