2017-08-25 62 views
0

我有兩個表,它們之間的連接需要永久。創建了相關索引,但顯然沒有被使用是我的猜測。慢連接,索引沒有在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具有TRADING_SYMBOLAS_ON_DATE作爲PK。對於一個日期,此表中可能有多個交易符號。

在表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表見。這可能會導致延遲。

理解是否正確,如果是,如何糾正,以便使用與交易符號有關的指數。我是否需要在交易代碼上使用全文索引才能使用它。

編輯

這裏有一些補充說明:

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爲133.2 g^

我有16GB的RAM。

+0

您需要附加索引'INTRADAY_PRICES_CASH(SnapshotDate,TradingSymbol)'或'ACTIVE_INSTRUMENTS_CASH(TRADING_SYMBOL,AS_ON_DATE)'。列的順序很重要,而且您的兩個表中的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關鍵 我\t範圍\t IND_AS_ON_DATE,IND1,IND3,IND5 \t IND_AS_ON_DATE Ç\t裁判\t IDX_SNAPSHOTDATE,IDX_SNAPSHOTDATETRADINGSYMBOL \t IDX_SNAPSHOTDATETRADINGSYMBOL – Kallol

+0

什麼是你所得到的數量和多少行你有在你的桌子上?這是一個非常簡單的查詢,可以從索引中完全計算,即使您的表中有十億行,也不需要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只有3,這意味着它只能使用索引的DATE一部分。

使用TRADING_SYMBOLTradingSymbol相同CHARACTER SETCOLLATION。 (建議你也拼寫它們。)不同的排序規則可防止使用索引(對於該列)。

難道這會給你相同的COUNT(*)

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

如果你開始於15日,爲什麼不說>= ... 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? –