建表:
SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for actor-- ----------------------------DROP TABLE IF EXISTS `actor`;CREATE TABLE `actor` ( `id` int(0) NOT NULL AUTO_INCREMENT, `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (`id`) USING BTREE, INDEX `idx_name`(`name`) USING BTREE # 对name建立索引) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of actor-- ----------------------------INSERT INTO `actor` VALUES (1, '郭德纲');INSERT INTO `actor` VALUES (2, '于谦');INSERT INTO `actor` VALUES (3, '高峰');INSERT INTO `actor` VALUES (4, '侯振');INSERT INTO `actor` VALUES (5, '栾云平');INSERT INTO `actor` VALUES (6, '岳云鹏');INSERT INTO `actor` VALUES (7, '朱云峰');INSERT INTO `actor` VALUES (8, '孔云龙');INSERT INTO `actor` VALUES (9, '张鹤伦');INSERT INTO `actor` VALUES (10, '周九良');SET FOREIGN_KEY_CHECKS = 1;查看执行计划:
EXPLAIN SELECT id, name FROM actorWHERE name LIKE '%云';虽然使用了索引,但是从rows来看还是进行的全盘扫描,导致索引失效。 如果%在右边是什么情况呢?
并不会导致索引失效。针对%在前的模糊查询如何优化呢?大致有以下几种方法。
2.创建全文索引,比较耗费资源3. 使用搜索引擎4. 使用辅助列优化思路:
创建一个虚拟列name_v作为name的映射,二者的字符串是逆序的对name和name_v分别建立索引在插入数据时,name正常插入,name_v插入的时name反转后的在查询时a. 针对%abc,去name_v列中去模糊查询cba%b. 针对abc%,去name列中正常模糊查询abc%c. 最后把两个查询结果通过UNION合并起来,得到最终结果集演示:
ALTER TABLE `actor` ADD COLUMN `name_v` VARCHAR(50) NOT NULL DEFAULT ''; # 创建辅助列ALTER TABLE `actor` ADD INDEX `id_name_v`(`name_v`); # 创建索引UPDATE `actor`SET `name_v` = REVERSE(`name`); # 更新表数据EXPLAIN SELECT id, name FROM actorWHERE name_v LIKE '云%' # 相当于name LIKE '%云'UNIONSELECT id, name FROM actorWHERE name LIKE '云%';总结如果模糊查询的列字符个数比较多,或者总体记录数较多,建议使用搜索引擎来做。 如果模糊查询的列字符个数不多且总体记录数不多,建议使用虚拟列来做。
作者:PhilJackson链接:https://juejin.cn/post/7379569983129255951