2014-10-08 4 views
2

У меня есть 2 стола - profile с 1 500 000 записей и indicator_trades с 12 000 000 записей. Следующий запрос, который возвращает 0 результатов, занимает около 10 секунд.Запрос MySQL не использует индекс правильно?

SELECT `trd`.`symbol`, `p`.`type` 
FROM `indicator_trades` AS `trd` 
INNER JOIN `profile` AS `p` ON `p`.`symbol` = `trd`.`symbol` 
WHERE `start_date` >= '2014-09-17' AND `p`.`type` = 2 

ОПИСАТЬ результаты:

+----+-------------+-------+--------+-----------------------+------------+---------+--------------------------+------+-------------+ 
| id | select_type | table | type | possible_keys   | key  | key_len | ref      | rows | Extra  | 
+----+-------------+-------+--------+-----------------------+------------+---------+--------------------------+------+-------------+ 
| 1 | SIMPLE  | trd | range | IDX_symbol,start_date | start_date | 4  | NULL      | 3662 | Using where | 
| 1 | SIMPLE  | p  | eq_ref | IDX_symbol,type  | IDX_symbol | 34  | barchart_data.trd.symbol | 1 | Using where | 
+----+-------------+-------+--------+-----------------------+------------+---------+--------------------------+------+-------------+ 

10 секунд, кажется, как аномально длительного времени для этого запроса, когда он использует ключи, но это просто принять, что долго обстругивать 3662 записей из 12,000,000 в indicator_trades таблица?

SHOW CREATE на двух таблицах:

CREATE TABLE `indicator_trades` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `symbol` varchar(32) NOT NULL, 
    `indicator_code` varchar(10) NOT NULL, 
    `start_date` date DEFAULT NULL, 
    `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `IDX_symbol` (`symbol`) USING BTREE, 
    KEY `start_date` (`start_date`), 
    KEY `indicator_code` (`indicator_code`) 
) ENGINE=InnoDB AUTO_INCREMENT=12582721 DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT | 

CREATE TABLE `profile` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `symbol` varchar(32) NOT NULL, 
    `type` int(11) DEFAULT NULL, 
    `lastupdate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `IDX_symbol` (`symbol`) USING BTREE, 
    KEY `type` (`type`), 
    KEY `exchange` (`exchange`) 
) ENGINE=InnoDB AUTO_INCREMENT=320948248 DEFAULT CHARSET=latin1 
+0

Нужно объединить 12 миллионов строк. Я думаю, что это внутреннее соединение, которое делает его медленным. –

+0

@ S.Pols Не нужно ли только присоединяться к 3662 записям, так как оптимизатор должен уменьшить набор данных с WHERE до присоединения? –

+1

Это звучит как переменная 'innodb_buffer_pool_size', чрезвычайно низкая, и вы попадаете на диск вместо ОЗУ. Что делает 'SHOW VARIABLES LIKE '% buffer_pool%';' show? –

ответ

0

На первый взгляд ваш запрос должен быть быстрым, а также описывается вывод EXPLAIN.

Вы не можете избежать диска читает, потому что нужно, чтобы получить поле, которое не находится в индексе, который используется (например, с использованием индекса start_date, но нужно тростниковый symbol поля, используя symbol индекс, но чтение type поля).

Также вы должны быть уверены, что все индексы загружены в память (настройка buffer_pool позволяет увеличить его).

Ваш запрос можно переписать так (я думаю, что такую ​​же производительность, следует ожидать):

SELECT `p`.`symbol`, 
     2 AS `type` 
FROM `profile` AS `p` 
WHERE `p`.`symbol` IN (SELECT DISTINCT(`trd`.`symbol`) 
         FROM `indicator_trades` AS `trd` 
         WHERE `trd`.`start_date` >= '2014-09-17') 
     AND `p`.`type` = 2 

Но вы можете запустить подзапрос и дайте нам знать, что скорость для него:

SELECT DISTINCT(`trd`.`symbol`) 
          FROM `indicator_trades` AS `trd` 
          WHERE `trd`.`start_date` >= '2014-09-17' 
Смежные вопросы