【 TiDB 使用环境】生产环境
【 TiDB 版本】TiDB-v6.1.3
遇到的问题:集群突然变慢,登录进去发现有个sql 在大量执行,TIKV-CPU 被拉满
表结构如下:
CREATE TABLE `tbl_tel_call_log` (
`record_id` varchar(100) NOT NULL DEFAULT '' COMMENT '话单id',
`ext_data` text NOT NULL COMMENT '扩展字段',
`source` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '来源',
.........
`called_name` varchar(40) NOT NULL DEFAULT '' COMMENT '被叫方的名称',
`call_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '呼叫类型,1-呼出,2-呼入',
`call_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '对应状态,1-成功调用下游,2-通话中,3-通话成功结束,4-通话失败(响铃未接),5-通话失败(未响铃)',
`duration` int(10) NOT NULL DEFAULT '0' COMMENT '通话时长(单位:s)',
`agent_ring_time` int(10) NOT NULL DEFAULT '0' COMMENT '座席响铃时间',
.......
`record_file` varchar(500) NOT NULL DEFAULT '' COMMENT '通话录音文件cos对象名',
`display_number` varchar(20) NOT NULL DEFAULT '' COMMENT '被叫方的可展示号码',
`encrypt_number` varchar(100) NOT NULL DEFAULT '' COMMENT '被叫方脱敏号码',
`create_name` varchar(40) NOT NULL DEFAULT '' COMMENT '创建人--邮箱前缀',
`create_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
`update_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
`last_modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '数据表最后更新时间',
`device_env` tinyint(4) NOT NULL DEFAULT '0' COMMENT '设备刷机状态',
`device_uniq_id` varchar(40) NOT NULL DEFAULT '' COMMENT '设备内编码',
PRIMARY KEY (`record_id`) /*T![clustered_index] NONCLUSTERED */,
KEY `idx_call_name` (`call_name`),
KEY `idx_record_id` (`record_id`),
KEY `idx_called_uid` (`called_uid`),
KEY `idx_call_status` (`call_status`),
KEY `idx_encrypt_time` (`encrypt_number`,`create_time`),
KEY `idx_outcall_record_id` (`outcall_record_id`),
KEY `idx_call_id` (`call_id`),
KEY `idx_create_time_role` (`create_time`,`role`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T! SHARD_ROW_ID_BITS=4 */
变慢的sql 如下:
SELECT count(1) FROM `tbl_tel_call_log` WHERE `encrypt_number` = '0415df6acde779843ac1b2172db07bbdb5c486662d002ffb' AND create_time >= 1680105600 and call_status in (3,5,31);
出问题时执行计划在dashboard 上看,使用了错误的索引KEY idx_call_status
(call_status
)
出问题执行这个sql 的执行计划如下:
使用的正确的索引: KEY
idx_encrypt_time
(encrypt_number
,create_time
)问题1: 这个sql 已经运行了好久了,为什么突然还行计划会变成使用call_status 这个索引
问题2:我在本地复现的时候,使用了force index 也不走正确的索引是为什么 ?
当我调整了 where 条件中 call_status 的位置, 执行计划就正常了。这是什么原因 ?