2010-11-18 10 views
1

私はSQLiteを学び、クエリを高速化する技術を探しています。ここでいくつかは、私が簡単にメガ秒になると、MSを絞り出すためにしようとしています。私は3つのテーブルを照会するだけですが、私は4つのテーブルを持つ1つのSQLiteデータベースを持っています。ここでは(私は、クエリを呼び出すためにRを使用しています)クエリです:私は、日付とシンボルとちょうど真空により各テーブルにインデックスを持っているSQLiteでGROUP BYのUNIONでINNER JOINを実行するには時間が必要ですか?

SELECT a.date, a.symbol, SUM (a.oi*a.contract_close) AS oi, c.ret, c.prc 
    FROM (SELECT date, symbol, oi, contract_close FROM ann 
      UNION 
      SELECT date, symbol AS sym, oi, contract_close FROM qtr 
      WHERE oi > 100 AND contract_close > 0 AND date > 20090600) a 
    INNER JOIN 
    (SELECT date, symbol || '1C' AS sym, ret, prc FROM crsp 
      WHERE prc > 5 AND date>20090600) c 
    ON a.date = c.date AND a.symbol = c.sym 
    GROUP BY a.date, a.symbol 

が、それは時間のように、まだ非常に遅いですプラス(と私は6ヶ月のサブセットを探していることに気付く...私は本当に2003年に戻って質問したい)。

これは単なるキャッシュサイズの問題ですか?私は比較的新しいノートパソコン(4GBのRAMを搭載したMacBook Pro)を持っています。ありがとう!ここで

.schemaです:

CREATE TABLE ann 
("date" INTEGER, 
symbol TEXT, 
contract_type_1 TEXT, 
contract_type_2 TEXT, 
product_type TEXT, 
block_volume INTEGER, 
oi_change INTEGER, 
oi INTEGER, 
efp_volume INTEGER, 
total_volume INTEGER, 
name TEXT, 
contract_change INTEGER, 
contract_open INTEGER, 
contract_high INTEGER, 
contract_low INTEGER, 
contract_close INTEGER, 
contract_settle INTEGER 
); 
CREATE TABLE crsp 
("date" INTEGER, 
symbol TEXT, 
permno INTEGER, 
prc REAL, 
ret REAL, 
vwretd REAL, 
ewretd REAL, 
sprtrn REAL 
); 
CREATE TABLE dly 
("date" INTEGER, 
symbol TEXT, 
expiration INTEGER, 
product_type TEXT, 
shares_per_contract INTEGER, 
"open" REAL, 
high REAL, 
low REAL, 
"last" REAL, 
settle REAL, 
change REAL, 
total_volume INTEGER, 
efp_volume INTEGER, 
block_volume INTEGER, 
oi INTEGER 
); 
CREATE TABLE qtr 
("date" INTEGER, 
symbol TEXT, 
total_volume INTEGER, 
block_volume INTEGER, 
efp_volume INTEGER, 
contract_high INTEGER, 
contract_low INTEGER, 
contract_open INTEGER, 
contract_close INTEGER, 
contract_settle INTEGER, 
oi INTEGER, 
oi_change INTEGER, 
shares_per_contract INTEGER, 
expiration INTEGER, 
product_type TEXT, 
unk TEXT, 
name TEXT 
); 
CREATE INDEX idx_ann_date_sym ON ann (date, symbol); 
CREATE INDEX idx_crsp_date_sym ON ann (date, symbol); 
CREATE INDEX idx_dly_date_sym ON ann (date, symbol); 
CREATE INDEX idx_qtr_date_sym ON ann (date, symbol); 

答えて

3

重要な情報はありません。これは、各テーブルに含まれる行の数と結果セットに含まれる行の数です。あなたが本当に膨大なデータセットを持っていない限り、クエリは1時間かかるべきではありません。私はあなたがあなたのUNIONで "WHERE句のみ二のテーブルに適用され、あなたが全体を取得していることを認識していると仮定し

  1. :、私はあなたのクエリで注目いくつかのことを言っ

    アン "テーブルが含まれていますか?

  2. 通常、UNIONによって提供される重複排除が本当に必要な場合を除き、UNION ALLは通常のUNIONよりも高速です。

  3. JOINの両側の日付フィールドにフィルタを繰り返す必要はありません。片面で十分です。JOINのどの面にフィルターをかけるかによって、スピードの異なる結果が得られます。これを両方の場所で使用すると、クエリオプティマイザを騙してしまう可能性があります。

  4. UNIONの2番目のSELECTで "AS sym"が何をしているのかわかりません。その列はUNIONの最初のSELECTからの出力で "symbol"という名前になりますメインのSELECTステートメントで名前シンボルに頼っています。

  5. メインのSELECTステートメントでは、集計関数にc.retとc.prcはありませんが、GROUP BYには含まれていませんので、どの値が期待されているかはわかりません結果には、cにはGROUP BYセットの複数の行が含まれています。

  6. 内部SELECTの一部としてJOIN値の1つを計算しているため、JOINを最適化することはできません。crspに計算されたシンボル値を格納せずに最適化できるようにJOIN条件を書き直す賢い方法があるかどうかはわかりません。

    シンボルと日付の値の分布によっては、(シンボル値の計算の問題を解決した場合のみ)インデックスの列の順序を逆にすることができます。

+0

これらの作業に感謝します。行数は次のとおりです:ann-1.5m、qtr-2.1m、crsp-14m –

+0

SELECT FROM crspの文字列連結は、スピードの点であなたを傷つけているはずです。 –

+0

ええ、私は本当にそう思っています...私はあなたが推薦した他の変更を行いました。それはまだ30分後になります。私はデータベースをそのままにしたいと思っていましたが、私はcrspテーブルをダンプして "1C"を見つけます。 –

1

INNERせずに、この実行がどのくらいの速さのJOINありません。結合の両方の半分の速度を調べます。

  • の選択を試してみて、労働組合の半分にSYMとシンボルのエイリアスを削除C.
  • 組合Aの代わりに、テーブルのに参加するC.
  • インナーから日付でシンボルを並べ替え、または両方の半分のエイリアス。
関連する問題