2

Я использую MySQL 5.6.19-log (согласно select version()).Как заставить MySQL «Использовать индекс для group-by»

У меня есть InnoDB таблицы что-то вроде этого:

CREATE TABLE `mytable` (
    `foo_id` bigint(20) NOT NULL, 
    `bar_id` bigint(20) NOT NULL, 
    `baz_id` bigint(20) NOT NULL, 
    PRIMARY KEY (`foo_id`,`bar_id`,`baz_id`) 
) 

Эта таблица хорошо работает со следующим запросом:

select 
    foo_id, 
    min(bar_id)-1 
from 
    mytable 
where 
    foo_id IN (
     1000,2000 
    ) 
group by 
    foo_id; 

+----+-------------+----------------------+-------+------------------------+---------+---------+------+-------+---------------------------------------+ 
| id | select_type | table    | type | possible_keys   | key  | key_len | ref | rows | Extra         | 
+----+-------------+----------------------+-------+------------------------+---------+---------+------+-------+---------------------------------------+ 
| 1 | SIMPLE  | mytable    | range | PRIMARY,bar_id_idx  | PRIMARY | 8  | NULL | 58245 | Using where; Using index for group-by | 
+----+-------------+----------------------+-------+------------------------+---------+---------+------+-------+---------------------------------------+ 

+----------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ 
| Query_ID | Duration | Query                                   | 
+----------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ 
|  1 | 0.00036575 | select foo_id, min(bar_id)-1 from mytable where foo_id IN (1000,2000) group by foo_id               | 
+----------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ 

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

select 
    foo_id, 
    min(bar_id)-1 
from 
    mytable 
where 
    foo_id = 1000 
group by 
    foo_id; 

+----+-------------+----------------------+------+------------------------+---------+---------+-------+--------+-------------+ 
| id | select_type | table    | type | possible_keys   | key  | key_len | ref | rows | Extra  | 
+----+-------------+----------------------+------+------------------------+---------+---------+-------+--------+-------------+ 
| 1 | SIMPLE  | mytable    | ref | PRIMARY,bar_id_idx  | PRIMARY | 8  | const | 873664 | Using index | 
+----+-------------+----------------------+------+------------------------+---------+---------+-------+--------+-------------+ 

+----------+------------+-----------------------------------------------------------------------------------------------------------------+ 
| Query_ID | Duration | Query                           | 
+----------+------------+-----------------------------------------------------------------------------------------------------------------+ 
|  1 | 0.07258075 | select foo_id, min(bar_id)-1 from mytable where foo_id = 1000 group by foo_id         | 
+----------+------------+-----------------------------------------------------------------------------------------------------------------+ 

Я думаю что-то вэнь неверно с планировщиком запросов MySQL. Есть ли какой-либо намек или что-то, чтобы заставить MySQL использовать индекс для группы по, когда число foo_id является только одним? Я пробовал analyze table mytable, но это не помогает.

Я знаю, что запрос select min(bar_id)-1 from mytable where foo_id = 1000 выполняется быстро, когда число foo_id - это только одно, но оно делает ветвь коду моего приложения, поэтому я бы хотел этого избежать.

+1

Поможет, если вы 'где foo_id в (1000)'? – shmosel

+0

К сожалению, это не так. Он производит точно такой же план и производительность запроса: 'где foo_id = 1000' –

+0

Что делать, если вы удаляете' group by'? – shmosel

ответ

0

его не ответ. его только образец из моего комментария

образца

mysql> EXPLAIN select 
    ->  foo_id, 
    ->  min(bar_id)-1 
    -> from 
    ->  mytable 
    -> where 
    ->  foo_id IN (
    ->   1000,2000 
    -> ) 
    -> group by 
    ->  foo_id; 
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+ 
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra     | 
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+ 
| 1 | SIMPLE  | mytable | NULL  | range | PRIMARY  | PRIMARY | 8  | NULL | 2 | 100.00 | Using where; Using index | 
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+ 
1 row in set, 1 warning (0,00 sec) 

mysql> 
mysql> EXPLAIN select 
    ->  foo_id, 
    ->  min(bar_id)-1 
    -> from 
    ->  mytable 
    -> where 
    ->  foo_id = 1000 
    -> group by 
    ->  foo_id; 
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+-------------+ 
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra  | 
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+-------------+ 
| 1 | SIMPLE  | mytable | NULL  | ref | PRIMARY  | PRIMARY | 8  | const | 1 | 100.00 | Using index | 
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+-------------+ 
1 row in set, 1 warning (0,00 sec) 

mysql> SELECT VERSION(); 
+-----------+ 
| VERSION() | 
+-----------+ 
| 5.7.14 | 
+-----------+ 
1 row in set (0,00 sec) 

mysql> SHOW CREATE TABLE mytable; 
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Table | Create Table                                                         | 
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| mytable | CREATE TABLE `mytable` (
    `foo_id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `bar_id` bigint(20) NOT NULL, 
    `baz_id` bigint(20) NOT NULL, 
    PRIMARY KEY (`foo_id`,`bar_id`,`baz_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=12804 DEFAULT CHARSET=latin1 | 
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0,00 sec) 

mysql> 
0

Попробуйте

select 
foo_id, 
min(bar_id)-1 
from 
    mytable 
where 
    foo_id LIKE 1000 
group by 
    foo_id; 

 Смежные вопросы

  • Нет связанных вопросов^_^