表结构
-- crawler2.keywordtask definition
CREATE TABLE `keywordtask` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`category` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`keyword` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`nums` int NOT NULL,
`start_date` datetime DEFAULT NULL,
`skip_filter` tinyint DEFAULT NULL,
`priority` tinyint DEFAULT NULL,
`track_source_id` int DEFAULT NULL,
`company_id` int DEFAULT NULL,
`meta_uuid` varchar(100) DEFAULT NULL,
`len_parse_result_list` mediumint DEFAULT NULL,
`push_uuid` varchar(64) DEFAULT NULL COMMENT '用于表示推送批次',
`parser` varchar(32) DEFAULT NULL,
`sorting_method` varchar(16) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `keywordtask_company_id_index` (`company_id`),
KEY `idx_updated_at` (`updated_at`),
KEY `index_meta_uuid` (`meta_uuid`),
KEY `idx_created_at` (`created_at`),
KEY `keywordtask_push_uuid_IDX` (`push_uuid`) USING BTREE,
KEY `idx_track_source_id_created_at_len_parse_result_list` (`track_source_id`,`created_at`,`len_parse_result_list`)
) ENGINE=InnoDB AUTO_INCREMENT=283001480 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
查询的 sql
SELECT
track_source_id,
DATE_FORMAT(created_at, '%Y-%m-%d') AS day,
COUNT(*) AS total_count,
SUM(CASE WHEN len_parse_result_list = 0 THEN 1 ELSE 0 END) AS len_parse_result_list_zero_count,
SUM(CASE WHEN len_parse_result_list IS NULL THEN 1 ELSE 0 END) AS len_parse_result_list_null_count,
SUM(CASE WHEN len_parse_result_list > 0 THEN 1 ELSE 0 END) AS len_parse_result_list_gte_zero_count
FROM
keywordtask
WHERE
created_at >= NOW() - INTERVAL 30 DAY
GROUP BY
track_source_id,
day
ORDER BY
track_source_id,
day;
使用 explain 分析的结果
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | keywordtask | index | idx_created_at,idx_track_source_id_created_at_len_parse_result_list | idx_track_source_id_created_at_len_parse_result_list | 14 | 134324154 | 50.0 | Using where; Using index; Using temporary; Using filesort |
我想知道的是,这个查询 sql 还存在「回表」吗? 以及是怎么判断的?
我觉得 mysql 设计的如果完善的话,是不应该回表的,因为查询 sql 需要的所有字段都在这个 idx_track_source_id_created_at_len_parse_result_list
二级索引中了。但是又担心 mysql 设计不完善,看到 created_at >= NOW() - INTERVAL 30 DAY
就不用后面的 len_parse_result_list
可以通过 explain 输出的 key_len 字段判断吗?
你可以根据 Extra 来判断 一般判断是否回表可以这样
1、出现了Using Index表示出现索引覆盖,不需要回表;
2、出现了Using Index Condition表示查找使用了索引,不需要回表查询,因为要过滤的字段在索引中。
3、Extra中是using index & using where,表示select的数据在索引中能找到,但需要根据where条件过滤,这种情况也不回表。
4、在使用到了索引,且Extra是Using where的情况下,才代表回表查询数据。
5、主键查询不回表,因为需要字段就是从聚簇索引上查找,不需要回表,但是Extra看不出来。