2

Ich benutze MySQL 5.6.19-Log (nach select version()).Wie erzwinge MySQL "Verwenden von Index für Group-by"

Ich habe eine InnoDB-Tabelle etwas wie folgt aus:

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`) 
) 

Diese Tabelle funktioniert gut mit der folgenden Abfrage:

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               | 
+----------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ 

Aber, wenn die Anzahl der foo_id in der where-Klausel ist nur , die Abfrage wird ziemlich langsam, wie folgt:

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         | 
+----------+------------+-----------------------------------------------------------------------------------------------------------------+ 

Ich denke, etwas wen t falsch mit dem Abfrageplaner von MySQL. Gibt es einen Hinweis oder etwas, um MySQL zu zwingen, den Index für die Gruppe zu verwenden, wenn die Nummer foo_id nur eine ist? Ich habe versucht analyze table mytable, aber es hilft nicht.

Ich weiß, dass eine Abfrage select min(bar_id)-1 from mytable where foo_id = 1000 ist schnell, wenn die Nummer foo_id ist nur eine, aber es macht eine Verzweigung zum Code meiner App, also möchte ich dies vermeiden.

+1

es, wenn Sie 'wo foo_id in (1000)' tut helfen? – shmosel

+0

Leider nicht. Es erzeugt genau den gleichen Abfrageplan und die gleiche Leistung wie 'wo foo_id = 1000' –

+0

Was passiert, wenn Sie die' group by' entfernen? – shmosel

Antwort

0

ist es nicht die Antwort. es ist nur ein Beispiel aus meinem Kommentar

Probe

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

Versuchen

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