此查询的最佳索引是什么?

时间:2020-08-16 22:14:58

标签: mysql sql indexing

我在MYSQL 8中有下表:

create table session
(
    ID                           bigint unsigned auto_increment
        primary key,
    session_id                   varchar(255)                                         null,
    username                     varchar(255)                                         null,
    session_status               varchar(255)                                         null,
    session_time                 int                                                  null,    
    time_created                 int                                                  null,
    time_last_updated            int                                                  null,
    time_ended                   int                                                  null,
    date_created                 date                                                 null,
);

我正在执行以下语句:

select * from session where username = VALUE and session_id = VALUE order by time_created desc

表加快查询速度的最佳索引是什么?

EXPLAIN查询告诉我我有两个潜在的索引,分别是:

create index username_3
    on session (username, time_created);

create index username_session_id_time_created_desc
    on session (username, session_id, time_created desc);

我本以为会选择索引'username_session_id_time_created_desc',但是EXPLAIN语句说却选择了索引'username_3'。

编辑*

SHOW CREATE TABLE会话的结果:

CREATE TABLE `session` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `session_id` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `username` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `session_status` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `session_time` int(11) DEFAULT NULL,
  `time_created` int(11) DEFAULT NULL,
  `time_last_updated` int(11) DEFAULT NULL,
  `time_ended` int(11) DEFAULT NULL,
  `date_created` date DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `username_3` (`username`,`time_created`),
  KEY `username_session_id_time_created_desc` (`username`,`session_id`,`time_created`)
) ENGINE=InnoDB AUTO_INCREMENT=76149265 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

EXPLAIN语句的结果:

select_type: SIMPLE
type: ref
possible_keys: username_3,username_session_id_time_created_desc
key: username_3
key_len: 768
ref: const
rows: 1
Extra: Using where

2 个答案:

答案 0 :(得分:0)

对于此查询:

select *
from session
where username = %s and session_id = %s
order by time_created desc

最佳索引为(username, session_id, time_created desc)。前两列可以按任意顺序排列。

答案 1 :(得分:0)

首先我以为你写错了,因为你写了

create index username_session_id_time_created_desc on session (username, session_id, time_created desc);

但是您的创建表显示了

KEY `username_session_id_time_created_desc` (`username`,`session_id`,`time_created`)

代替

KEY `username_session_id_time_created_desc` (`username`,`session_id`,`time_created` DESC)

但是,由于username_3 (I did not read it all)

,我现在认为它在MySQL 8.0中使用backward_index_scan

如何判断:简单的filesort中没有EXPLAIN,因此优化器必须可以使用username_3索引对结果集进行排序。 (如果从任何索引中删除time_created,您将看到Using filesort。如果您未使用MySQL 8.0,则可能是您的版本中的username_3索引也可以进行排序。)

Fiddle in 5.7显示"key": "username_session_id_time_created_desc", sometimes,但并非总是...这可能取决于索引长度(字段长度)。

Whereas in MySQL 8.0显示"key": "username_3","backward_index_scan": true,

With only the 3 column index它显示了较低的查询成本,那么为什么要选择其他索引?

我的猜测是2列索引要短得多,并且由于可以进行向后索引扫描,因此排序很便宜,并且优化器仍然更喜欢具有更少的IO和更多的计算。