mysql: 为什么下面查询未使用的联合索引?

mysql: why below query unused union index?

table a
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int(11)     | NO   | PRI | NULL    |       |
| uid      | int(11)     | YES  | MUL | NULL    |       |
| channel  | varchar(20) | YES  |     | NULL    |       |
| createAt | datetime    | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+

table a index: a_index_uid_createAt` (`uid`,`createAt`)


table b:
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| uid       | int(11)     | NO   | PRI | NULL    |       |
| date      | date        | YES  | MUL | NULL    |       |
| channel   | varchar(20) | YES  | MUL | NULL    |       |
| gender    | smallint(6) | YES  | MUL | NULL    |       |
| chargeAmt | int(11)     | YES  |     | 0       |       |
| revised   | smallint(6) | YES  |     | 0       |       |
| createAt  | datetime    | YES  |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+

查询 st:

select  DATE(a.createAt) date,a.channel,b.chargeAmt
    FROM  a, b
    where  a.uid = b.uid
      and  a.createAt >= '2021-05-10 00:00:00'
      and  a.createAt <= '2021-05-10 23:59:59';

解释:

+----+-------------+-------+--------+-------------------------------------------------+---------+---------+--------------+--------+-------------+
| id | select_type | table | type   | possible_keys                                   | key     | key_len | ref          | rows   | Extra       |
+----+-------------+-------+--------+-------------------------------------------------+---------+---------+--------------+--------+-------------+
|  1 | SIMPLE      | a     | ALL    | a_index_uid_createAt | NULL    | NULL    | NULL         | 172725 | Using where |
|  1 | SIMPLE      | b     | eq_ref | PRIMARY                                         | PRIMARY | 4       | xiehou.r.uid |      1 |             |
+----+-------------+-------+--------+-------------------------------------------------+---------+---------+--------------+--------+-------------+

为什么? a_index_uid_createAt 索引无效!

请使用JOIN .. ON语法:

select  DATE(a.createAt) date, a.channel, b.chargeAmt
    FROM  a
    JOIN  b  ON  a.uid = b.uid   -- How the tables are related
    WHERE  a.createAt >= '2021-05-10                    -- filtering
      and  a.createAt  < '2021-05-10 + INTERVAL 1 DAY;  -- filtering

优化器在看到 JOIN 时首先决定从哪个 table 开始。首选table是带过滤的,即a.

要进行过滤,它需要一个 开始 WHERE 子句中提到的列的索引。

另外一个table看ON就可以了,好像有PRIMARY KEY(uid)

所以,唯一有用的索引是

a:  INDEX(createAt)

任何 INDEX(uid, ...) 都可能未被使用,因为它以现有索引开始,即 PRIMARY KEY(uid).

(以后请用SHOW CREATE TABLE,比DESCRIBE更具描述性。)