0

(以下の更新を参照)

C#.Net アプリケーション内から約 500,000 行の非常に単純な Sqlite データテーブルをクエリすると、クエリのパフォーマンスが低下するという問題があります (約 5 秒)。

LinqPad と 2 つのデータベース ブラウザー (どちらも QtSql ベース) を使用して、まったく同じデータベースでまったく同じクエリを試しましたが、10 倍高速 (~0.5 秒) で実行されます。同じクエリ、同じデータベース、異なるアプリ、私のものだけが高速に動作しません。

値を返すか、単に Count(*) を返すかに関係なく、ほとんど違いはありません。

私はもう試した:

  • .Net 3.5/4/4.5のそれぞれのビルド
  • AnyCPU/x86/x64のそれぞれのビルド
  • System.Data.Sqlite、sqlite-net のそれぞれを使用し、COM 経由で sqlite3 dll に直接アクセスする
  • WPF/WinFormごとにビルド
  • クエリのさまざまなバリエーション

これらのどれも、クエリ時間に顕著な違いをもたらしません。

JOIN を使用してクエリを書き直すと役立つことはわかっていますが、LinqPad/Sql ブラウザーでは同じクエリが正常に機能するのに、作成しようとしているアプリでは機能しない理由がわかりません。かなり基本的な何かが欠けているに違いありません。

例の表:

"CREATE TABLE items(id INTEGER PRIMARY KEY, id1 INTEGER, id2 INTEGER, value INTEGER)"

クエリ文字列の例 (基本的に、サブクエリを使用するクエリはすべて時間がかかります):

SELECT count(*) 
FROM items WHERE 
id2 IN 
(
    SELECT DISTINCT id2 FROM items WHERE id1 IN 
    (
        SELECT DISTINCT id1 FROM items WHERE id2 = 100000 AND value = 10
    )
    AND value = 10
) 
AND value = 10 
GROUP BY id2

これはおそらく JOINS とインデックス作成を使用して書き直して高速化できることはわかっていますが、このクエリは他のアプリよりもはるかに高速に動作するという事実は変わりません。何を試しても同じクエリの実行が非常に遅くなる理由について、ここで何が欠けていますか?

更新: sqlite のバージョンが問題に関係しているようです。従来の System.Data.Sqlite v1.0.66.0 を使用すると、クエリは他のアプリと同じように実行されますが、より新しいバージョンを使用すると遅くなります。これがどのバージョンで正確に何を変更したかは特定していませんが、具体的には System.Data.Sqlite ではなく、基礎となる sqlite3 バージョンに関係していると確信しています。この状況でサブクエリが非常に遅くなる原因となる変更を誰かが知っている場合、または sqlite の新しいバージョンでサブクエリをより速く実行できる設定または何かがある場合は、私に知らせてください!

繰り返しますが、クエリは例であり、理想的ではなく、部分的に冗長です...問題は、なぜ一方では機能し、他方では機能しないのかについてです。

追加のご意見をお寄せいただきありがとうございます。

更新:解決済み

以下の私の答えを見てください。

4

3 に答える 3

0

試す

SELECT ID1.id2, count(*) 
FROM items ID2
JOIN items ID1
  on ID2.id2 = ID1.id1
 and ID1.id2 = 100000 
 and ID1.value = 10 
 and ID2.valu3 = 10
group by ID1.id2
于 2013-02-11T17:11:48.160 に答える
0

OKは、SQLite1.7.0で導入された自動インデックス作成に関係していることがわかりました。私の状況では、インデックスなしでこの種のテーブルにサブクエリを使用すると、SQLiteが自動インデックスを作成するのに時間がかかり、クエリで発生していた追加のオーバーヘッドが発生していました。

解決策は次を使用することでした:

PRAGMA automatic_index=OFF;

「IN」句を使用するクエリの開始時。

列にインデックスを作成することもこれを解決する可能性があります(テストされていません)が、この特定の状況では、インデックスを作成するために必要な追加のサイズ/ディスク使用量は価値がありません。

これは、LinqPadSQLiteプラグインと私が使用していたデータベースビューアが古いバージョンのsqliteに基づいていることも示唆しています。

詳細については、次を参照してください。

http://www.sqlite.org/src/info/8011086c85c6c4040

http://www.sqlite.org/optoverview.html#autoindex

回答してくださった皆様、ありがとうございました。

于 2013-02-12T08:34:02.307 に答える
0

いくつかの提案:

クエリを作り直したり、インデックスを追加したりしたくないと言います。それはここでやるべきことです。インデックスがなければ、sqlite は 500,000 行のテーブルを少なくとも 1 回 (または複数回) スキャンする必要があります。

上記のクエリに基づいて、列id1とにインデックスを追加しますid2

もう1つのことは、上記のクエリが少し冗長に見えることです。理由があるかもしれませんが、なぜクエリが複雑になるのかわかりません。単純化されたクエリ:

select count(*)
from items
where id2 = 100000 and value = 10

于 2013-02-11T15:03:38.093 に答える