2016-11-15 67 views
0

我有表具有相同的架構的MySQL不使用主索引時,它與子查詢結果相比較

CREATE TABLE `stock` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `currency` varchar(3) COLLATE utf8_unicode_ci NOT NULL, 
    `against` varchar(3) COLLATE utf8_unicode_ci NOT NULL, 
    `date` date NOT NULL, 
    `time` time NOT NULL, 
    `rate` double(8,4) NOT NULL, 
    `ask` double(8,4) NOT NULL, 
    `bid` double(8,4) NOT NULL, 
    `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    PRIMARY KEY (`id`), 
    KEY `stock_currency_index` (`currency`), 
    KEY `stock_against_index` (`against`), 
    KEY `stock_date_index` (`date`), 
    KEY `stock_time_index` (`time`), 
    KEY `created_at_index` (`created_at`) 
) ENGINE=InnoDB AUTO_INCREMENT=244221 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

當我執行此查詢MySQL已經使用指數

mysql> explain select max(id) from stock group by currency; 
+----+-------------+-------+------------+-------+----------------------+----------------------+---------+------+------+----------+--------------------------+ 
| id | select_type | table | partitions | type | possible_keys  | key     | key_len | ref | rows | filtered | Extra     | 
+----+-------------+-------+------------+-------+----------------------+----------------------+---------+------+------+----------+--------------------------+ 
| 1 | SIMPLE  | stock | NULL  | range | stock_currency_index | stock_currency_index | 11  | NULL | 2 | 100.00 | Using index for group-by | 
+----+-------------+-------+------------+-------+----------------------+----------------------+---------+------+------+----------+--------------------------+ 
1 row in set, 1 warning (0.00 sec) 

而且當我執行這個查詢mysql也有使用主索引

mysql> explain select * from stock where id in (244221, 244222); 
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ 
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra  | 
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ 
| 1 | SIMPLE  | stock | NULL  | range | PRIMARY  | PRIMARY | 4  | NULL | 2 | 100.00 | Using where | 
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ 
1 row in set, 1 warning (0.00 sec) 

但是當我結合這兩個查詢PRIMARY ind前不使用...我很困惑。我做錯了什麼?

mysql> explain select * from stock where id in (select max(id) from stock group by currency); 
+----+-------------+-------+------------+-------+----------------------+----------------------+---------+------+--------+----------+--------------------------+ 
| id | select_type | table | partitions | type | possible_keys  | key     | key_len | ref | rows | filtered | Extra     | 
+----+-------------+-------+------------+-------+----------------------+----------------------+---------+------+--------+----------+--------------------------+ 
| 1 | PRIMARY  | stock | NULL  | ALL | NULL     | NULL     | NULL | NULL | 221800 | 100.00 | Using where    | 
| 2 | SUBQUERY | stock | NULL  | range | stock_currency_index | stock_currency_index | 11  | NULL |  2 | 100.00 | Using index for group-by | 
+----+-------------+-------+------------+-------+----------------------+----------------------+---------+------+--------+----------+--------------------------+ 
2 rows in set, 1 warning (0.00 sec) 
+1

幾點意見:1)認真考慮將日期和時間存儲爲一個單獨的實體。 2)您極可能不會將價格,問題和出價存儲爲DECIMAL以外的其他產品 – Strawberry

+0

@Strawberry非常感謝您提供的有用評論。這將是最好使用十進制類型,而不是雙倍。 –

回答

1

首先,嘗試重寫查詢爲:

select s.* 
from stock s join 
    (select max(id) as maxid 
     from stock 
     group by currency 
    ) ss 
    on ss.maxid = s.id; 

其次,我會很想把上stock(currency, id)的指標,使用方法:

select s.* 
from stock s 
where s.id = (select max(s2.id) from stock s2 where s2.currency = s.currency); 

執行以上任一執行更好?

+0

我還沒有設法構建一個方案,其中選項2優於選項1 – Strawberry

+0

非常感謝。第一個查詢工作完美! –

+0

@Strawberry。 。 。正確的索引是'stock(currency,id desc)'。但是,MySQL忽略了「DESC」。 –