1

完了するまでに約 4 秒かかる非常に単純なクエリがあります。

SELECT MAX(Date), Bond_Id, Sell_Price FROM quote GROUP BY Bond_Id;

テーブルも単純で、約 31K レコードしかありません。スキーマは次のとおりです。

CREATE TABLE の引用 (
    _id INTEGER PRIMARY KEY AUTOINCREMENT,
    Bond_Id INTEGER NOT NULL、
    日付テキスト NOT NULL、
    Buy_Yield REAL NOT NULL、
    Sell_Yield REAL NOT NULL,
    Buy_Price REAL NOT NULL、
    Sell_Price REAL NOT NULL、
    Base_Price REAL NOT NULL、
    FOREIGN KEY (Bond_Id) REFERENCES Bonds(_id));

CREATE INDEX quotesNdx ON quotes(Bond_Id);

SQLite のドキュメントを調べたところ、クエリ時間を 7 秒から 4 秒に短縮できましたが、これはまだ許容できません。私は何日も頭を悩ませてきましたが、運がありません。私はすでにANALYZE、いくつかの追加の複合インデックスを試し、また外部キーを削除しようとしました。何もない。

EXPLAIN の出力は次のとおりです。

0 Trace 0 0 0 Explain select max(date),bond_id,sell_price from quotes group by bond_id; 00
1 ヌープ 0 0 0 00
2 整数 0 6 0 00
3 整数 0 5 0 00
4 後藤 0 20 0 00
5 整数 1 6 0 00
6 戻る 0 0 0 00
7 IfPos 5 9 0 00
8 戻る 0 0 0 00
9 AggFinal 1 1 0 max(1) 00
10 Sコピー 1 9 0 00
11 Sコピー 2 10 0 00
12 Sコピー 3 11 0 00
13 結果行 9 3 0 00
14 戻る 0 0 0 00
15 ヌル 0 2 0 00
16 ヌル 0 3 0 00
17 ヌル 0 4 0 00
18 ヌル 0 1 0 00
19 戻る 0 0 0 00
20 ゴサブ 0 15 0 00
21 後藤 0 48 0 00
22 SetNumColumns 0 7 0 00
23 オープンリード 0 6 0 00
24 SetNumColumns 0 2 0 00
25 OpenRead 2 7 0 keyinfo(1,BINARY) 00
26 巻き戻し 2 44 13 0 00
27 ヌープ 2 -7 13 0 01
28 IdxRowid 2 16 0 00
29 ムーブゲ 0 0 16 00
30 列 2 0 8 00
31 Eq 7 36 8 collseq(BINARY) 10
32 移動 8 7 0 00
33 ゴサブ 0 7 0 00
34 IfPos 6 47 0 00
35 ゴサブ 0 15 0 00
36 列 0 2 17 00
37 CollSeq 0 0 0 collseq(BINARY) 00
38 AggStep 0 17 1 max(1) 01
39 Sコピー 7 2 0 00
40 列 0 6 3 00
41 リアルアフィニティ 3 0 0 00
42 整数 1 5 0 00
43 次の 2 27 0 00
44 クローズ 0 0 0 00
45 クローズ 2 0 0 00
46 ゴサブ 0 7 0 00
47 停止 0 0 0 00
48 トランザクション 0 0 0 00
49 ベリファイCookie 0 9 0 00
50 テーブルロック 0 6 0 クォート 00
51 後藤 0 22 0 00

任意のヒント?

4

3 に答える 3

0

回答ありがとうございます。実際、私のクエリの違反者は「GROUP BY」でした。SQLite の SELECT (http://sqlite.org/lang_select.html) ドキュメントのこの特定の箇所を読むことで、解決策を見つけることができました。

「SELECT ステートメントが GROUP BY 句を含む集計クエリである場合、GROUP BY 句の一部として指定された各式は、データセットの各行に対して評価されます。次に、各行は、に基づいて「グループ」に割り当てられます。結果; GROUP BY 式の評価結果が同じである行は、同じグループに割り当てられます. 行をグループ化する目的で、NULL 値は等しいと見なされます. テキスト値を比較するための照合順序を選択するための通常の規則GROUP BY 句の式を評価するときに適用されます. GROUP BY 句の式は、結果に表示される式である必要はありません. GROUP BY 句の式は、集計式である必要はありません.

したがって、解決策は、(Date, Bond_Id) を含む複合インデックスを作成し、クエリを次のように置き換えることでした。

SELECT Date, Bond_Id, Sell_Price FROM Quotes
   WHERE Bond_Id=Bonds._id
   AND Date=(SELECT MAX(Date) FROM Quotes);

これで、このクエリは 1 秒もかからずに完了するようになりました。これはすばらしいことです。

于 2013-09-24T11:10:01.200 に答える
-1

あなたのクエリ:

SELECT MAX(Date), Bond_Id, Sell_Price FROM quote GROUP BY Bond_Id;

FIRST : クエリが正しくありません。フィールド名として予約語を使用しないでください。あなたの場合、フィールドは「日付」です

GROUP BY で任意のフィールドを使用する場合は、SELECT 内の他のすべてのフィールドもグループ化関数 (MIN/MAX/COUNT/など) と共に使用する必要があります。

正しいクエリは次のとおりです。

SELECT MAX(日付), Bond_Id FROM クォート GROUP BY Bond_Id;

また

SELECT Bond_Id, MAX(Sell_Price) FROM Quotes GROUP BY Bond_Id HAVING "Date" = MAX("Date");

2番目:

MIN/MAX/... および GROUP BY で使用されるすべてのフィールドのインデックスを作成する必要があります

于 2013-09-19T12:51:37.363 に答える