far*_*ess 5 mysql index optimization index-tuning explain
对于以下查询
SELECT MAX(CONCAT(date, ' ', last_entry)) AS LAST_LOG
FROM entry_log
WHERE TRIM(LEADING 0 FROM card_no)='2948'
Run Code Online (Sandbox Code Playgroud)
我已经索引了
date
card_no
date,last_entry
date,last_entry,card_no
Run Code Online (Sandbox Code Playgroud)
我的解释显示
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE entry_log index NULL date_last_card 158 NULL 103766 Using where; Using index
Run Code Online (Sandbox Code Playgroud)
我的解释扩展节目
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE entry_log index NULL date_last_card 158 NULL 103766 100.00 Using where; Using index
Run Code Online (Sandbox Code Playgroud)
我想知道我可以删除/使用哪个索引,我的路径是否正确,我应该如何提高上述查询的执行时间?
CREATE TABLE `entry_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`card_no` varchar(50) NOT NULL,
`date` date NOT NULL,
`first_entry` time NOT NULL,
`last_entry` time NOT NULL,
`all_entry` text NOT NULL,
`entry_time` datetime NOT NULL,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9308 DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)
假设card_noandlog_entry具有VARCHAR或CHAR类型,我首先会在 上添加一个索引(card_no, date, last_entry):
ALTER TABLE entry_log
ADD INDEX card_no__date__last_entry__ix
(card_no, date, last_entry) ;
Run Code Online (Sandbox Code Playgroud)
然后使用这个查询:
SELECT CONCAT(date, ' ', last_entry) AS LAST_LOG
FROM entry_log
WHERE card_no = LPAD('2948', 32, '0')
ORDER BY date DESC, last_entry DESC
LIMIT 1 ;
Run Code Online (Sandbox Code Playgroud)
列表中的值IN应包括类型允许的最大长度的所有长度。上面的例子是针对VARCHAR(8).
更新:由于澄清了该card_no列始终为 32 个字符并用零填充,因此查询条件简化为:
toWHERE card_no IN ('2948', '02948', '002948', ..., '000...0002948')
WHERE card_no = RIGHT(CONCAT('000..00', '2948'), 32)或简单地为
WHERE card_no = LPAD('2948', 32, '0')