【发布时间】:2020-09-19 01:18:05
【问题描述】:
我有以下表格:
显示创建表 access_token_status;
CREATE TABLE `access_token_status` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`status` varchar(10) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `status` (`status`),
KEY `idx_access_token_status_status_lookup_2` (`status`,`id`),
KEY `idx_access_token_status_status_lookup_1` (`id`,`status`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
和
显示创建表用户;
CREATE TABLE `user` (
`id` varchar(17) NOT NULL,
`short_lived_access_token_status_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_user_status_lookup_1` (`id`,`short_lived_access_token_status_id`),
KEY `idx_user_status_lookup_2` (`short_lived_access_token_status_id`,`id`),
KEY `ix_user_short_lived_access_token_status_id` (`short_lived_access_token_status_id`),
CONSTRAINT `user_ibfk_1` FOREIGN KEY (`short_lived_access_token_status_id`) REFERENCES `access_token_status` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
和
显示创建表帐户;
CREATE TABLE `account` (
`id` varchar(17) NOT NULL,
`user_id` varchar(17) NOT NULL,
`track` tinyint(1) NOT NULL,
`estimated_time_to_regain_access` int(11) NOT NULL,
`media_list_fetched_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_account_next_fetch_lookup` (`user_id`,`estimated_time_to_regain_access`,`track`,`media_list_fetched_at`),
CONSTRAINT `account_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `account_chk_1` CHECK ((`track` in (0,1)))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
当我尝试解释以下查询时
explain select a.*
from account a
inner join user u
on a.user_id = u.id
inner join access_token_status as s
on u.short_lived_access_token_status_id = s.id and s.status = 'valid'
where
u.short_lived_access_token_status_id = 3
and a.estimated_time_to_regain_access = 0
and a.track = true
and a.media_list_fetched_at > '2020-05-30 12:31:01'
limit 1
for update of a SKIP LOCKED
我得到这个输出:
# id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
'1', 'SIMPLE', 's', NULL, 'const', 'PRIMARY,status,idx_access_token_status_status_lookup_2,idx_access_token_status_status_lookup_1', 'PRIMARY', '4', 'const', '1', '100.00', NULL
'1', 'SIMPLE', 'a', NULL, 'index', 'idx_account_next_fetch_lookup', 'idx_account_next_fetch_lookup', '80', NULL, '2', '50.00', 'Using where; Using index'
'1', 'SIMPLE', 'u', NULL, 'eq_ref', 'PRIMARY,idx_user_status_lookup_1,idx_user_status_lookup_2,ix_user_short_lived_access_token_status_id', 'PRIMARY', '70', 'media_meta.a.user_id', '1', '100.00', 'Using where'
似乎某些表没有使用索引。这是我的情况的一个问题,因为扫描的行被锁定并且其他查询将跳过它们(由于 SKIP LOCKED 需要确保查询不会相互阻塞)
我不确定我缺少什么索引,或者我是否需要更改查询中的某些内容
【问题讨论】:
-
请注意,没有 ORDER BY 的 LIMIT 是毫无意义的
-
我会尝试更改索引的顺序,以便 user_id 出现在末尾span>
-
另外,我想不出一个 id 不是整数的充分理由
-
在我的用例中顺序无关紧要,我没有提供这样的细节以避免分心。但这会影响执行计划吗?你对索引是正确的,这也是可能超出问题范围的业务逻辑,除非你认为这正在改变执行计划(我确实尝试过整数 id,但计划没有改变)我确实尝试过添加一个新索引user_id 最后,确实有效,谢谢
-
如果您认为问题已解决,请随时回答问题并接受您自己的回答,否则删除问题。
标签: mysql join query-optimization sql-execution-plan