2017-08-25 10 views
0

私は2つのテーブルを持っており、それらの間の結合は永遠にかかります。関連するインデックスを作成しましたが、明らかに使われていないのは私の推測です。スロージョイン、インデックスがvarcharカラムで使用されていません

表1:

CREATE TABLE `INTRADAY_PRICES_CASH` (
`TradingSymbol` varchar(100) CHARACTER SET latin1 NOT NULL, 
`SnapshotDateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP, 
`Open` double NOT NULL, 
`Low` double NOT NULL, 
`High` double NOT NULL, 
`Close` double NOT NULL, 
`Volume` double NOT NULL, 
`SnapshotDate` date NOT NULL, 
`SnapshotTime` time NOT NULL, 
`UpdateToDBTime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
PRIMARY KEY (`TradingSymbol`,`SnapshotDateTime`), 
KEY `IDX_SNAPSHOTDATE` (`SnapshotDate`), 
KEY `IDX_SNAPSHOTDATETIME` (`SnapshotDateTime`), 
KEY `IDX_SNAPSHOTTIME` (`SnapshotTime`), 
KEY `IDX_TRADINGSYMBOL` (`TradingSymbol`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

表2:

CREATE TABLE `ACTIVE_INSTRUMENTS_CASH` (
    `INSTRUMENT_ID` bigint(20) NOT NULL AUTO_INCREMENT, 
    `INSTRUMENT_TOKEN` bigint(20) DEFAULT NULL, 
    `EXCHANGE_TOKEN` bigint(20) DEFAULT NULL, 
    `TRADING_SYMBOL` varchar(100) COLLATE utf8_unicode_ci NOT NULL, 
    `INSTRUMENT_NAME` varchar(500) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `EXPIRY` date DEFAULT NULL, 
    `LOT_SIZE` double DEFAULT NULL, 
    `TICK_SIZE` float DEFAULT NULL, 
    `INSTRUMENT_TYPE` varbinary(10) DEFAULT NULL, 
    `SEGMENT` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `EXCHANGE` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `AS_ON_DATE` date NOT NULL, 
    PRIMARY KEY (`INSTRUMENT_ID`), 
    UNIQUE KEY `IND_AS_ON_DATE` (`AS_ON_DATE`,`TRADING_SYMBOL`), 
    KEY `IND1` (`AS_ON_DATE`), 
    KEY `IND2` (`INSTRUMENT_TOKEN`), 
    KEY `IND3` (`TRADING_SYMBOL`), 
    KEY `IND4` (`INSTRUMENT_TYPE`) 
) ENGINE=InnoDB AUTO_INCREMENT=196606 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

表2 PKとしてTRADING_SYMBOLAS_ON_DATEを有しています。 1つの日付に対して、この表には複数の取引記号が存在する可能性があります。

表1では、同じ取引記号と日付の組み合わせについて、同じ日付の様々な分の記号の様々な価格を表す複数の行があります。

ここで、これらのテーブルを結合して、両方のテーブルで取引記号と日付の組み合わせに一致する行の数を確認します。

SELECT COUNT(*) FROM INTRADAY_PRICES_CASH C, ACTIVE_INSTRUMENTS_CASH I 
WHERE C.`SnapshotDate`>'2017-08-14' 
AND I.`TRADING_SYMBOL`=C.`TradingSymbol` 
AND I.`AS_ON_DATE`=C.`SnapshotDate` 

それが使用されていることを示していることを説明:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE I range IND_AS_ON_DATE,IND1,IND3 IND_AS_ON_DATE 3 \N 15066 Using where; Using index 
1 SIMPLE C ref IDX_SNAPSHOTDATE IDX_SNAPSHOTDATE 3 u754793479_stock.I.AS_ON_DATE 771 Using where; Using index 

不思議私はそれがTradingSymbolに関連するテーブルの両方でのインデックスのいずれかを使用して参照していけません。これはおそらくこれを遅らせる原因になります。

この理解は正しいと思いますが、取引記号に関連するインデックスを使用するように修正する方法です。これを使用するには取引記号に全文索引が必要ですか?ここで

EDITは、いくつかの追加の明確化です:

INTRADAY_PRICES_CASHは69700675個の行が含まれています。 ACTIVE_INSTRUMENTS_CASHには190177行が含まれます。

SELECT COUNT(*) FROM INTRADAY_PRICES_CASH C WHERE C.SnapshotDate>'2017-08-14' 戻っ3911679行

私のホスティングプロバイダはinnodb_index_statsへのアクセスを提供していません。したがって、このクエリを発射することはできません。 SELECT *, stat_value * @@innodb_page_size FROM mysql.innodb_index_stats WHERE table_name = 'INTRADAY_PRICES_CASH' and stat_name = 'size' and indexname = 'IDX_SNAPSHOTDATETRADINGSYMBOL';

select @@innodb_buffer_pool_sizeは、私は16ギガバイトのRAMを持って133.2 G

です。

+0

追加インデックス 'INTRADAY_PRICES_CASH(SnapshotDate、TradingSymbol)'または 'ACTIVE_INSTRUMENTS_CASH(TRADING_SYMBOL、AS_ON_DATE)'が必要です。列の順序は重要であり、現在、2つの表の2列の索引に対して異なるものがあります。 – Solarflare

+0

ありがとうございます。両方を追加しました。説明はINTRADAY_PRICES_CASH(SnapshotDate、TradingSymbol)を使用していますが、まだ36分かかります。 'KEY' IND5'( 'TRADING_SYMBOL'、' AS_ON_DATE')と 'KEY' IDX_SNAPSHOTDATETRADINGSYMBOL'( 'SnapshotDate'、' TradingSymbol')のインデックスです。説明表示されています。あなたが取得している、あなたはどのように多くの行なければならないの数は何台\tタイプ\t possible_keys \tキー I \t範囲\t IND_AS_ON_DATE、IND1、IND3、IND5 \t IND_AS_ON_DATE C \t REF \t IDX_SNAPSHOTDATE、IDX_SNAPSHOTDATETRADINGSYMBOL \t IDX_SNAPSHOTDATETRADINGSYMBOL – Kallol

+0

あなたのテーブルに?これは、インデックスから完全に計算できる非常に簡単なクエリです。テーブルに10億行があっても36分かかることはありません。 'TradingSymbol'には10個以上の可能性の高い100文字が含まれていますか?シンボルを表すintで置き換えると、シンボルの平均長さに比べてスピードが向上します。 – Solarflare

答えて

0

より良いエイリアスを選択してください - 両方のテーブルには、最初のCとI.

を持つ優先JOIN...ONを使用してください。

SELECT COUNT(*) 
    FROM INTRADAY_PRICES_CASH AS p 
    JOIN ACTIVE_INSTRUMENTS_CASH AS a 
      ON a.`TRADING_SYMBOL` = p.`TradingSymbol` 
     AND a.`AS_ON_DATE`  = p.`SnapshotDate` 
    WHERE p.`SnapshotDate`>'2017-08-14' 

key_lenは、それが唯一のインデックスのDATE一部を使用していることを意味している、唯一の3がどのように注意してください。

TRADING_SYMBOLTradingSymbolため同じCHARACTER SETCOLLATIONを使用してください。 (あなたにも同じことを綴ってください)異なる照合はインデックスの使用を防ぎます(その列に対して)。

同じではないでしょうかCOUNT(*)?あなたは15日に開始する場合

SELECT COUNT(*) 
    FROM INTRADAY_PRICES_CASH 
    WHERE p.`SnapshotDate`>'2017-08-14'; 

、なぜ>= ... 15代わりに> ... 14言いませんか?これはDATETIMEと同様にDATEのために働くでしょう。

他のテーブルはINSTRUMENT_IDを使用していますか?または、その列を削除してUNIQUEキーをPRIMARYに昇格できますか?

本当に結合が必要な場合は、他のインデックス提案があるかもしれません。

+0

これを改善するための指針をありがとう。 'INTRADAY_PRICES_CASH'からのカウントは同じカウントを与えます。しかし、私は 'ACTIVE_INSTRUMENTS_CASH'に同じ表現を持つ' INTRADAY_PRICES_CASH'からのセットだけでダウンストリームクエリを処理させるようにしたいと思います。 @Solarflareのように照合順序を変更しました。パフォーマンスは低下しましたが、実行には5分かかります – Kallol

+0

'INTRADAY_PRICES_CASH'の行数はいくつですか?結果として得られる 'COUNT(*)'は何ですか? 'innodb_buffer_pool_size'の値は何ですか?あなたはどれくらいのRAMを持っていますか? –

関連する問題