2026/1/18 17:01:47
网站建设
项目流程
请人做网站多少钱,网站风格定位怎么写,工业互联网企业排名,有了域名怎么制作网站关注我们,设为星标,每天7:30不见不散,每日java干货分享你接到了一个运营需求#xff1a;“帮我导出所有 Gmail 邮箱 的用户” 或者 “查一下所有 尾号是 1234 的手机号”。直觉写法#xff1a;SELECT * FROM users WHERE email LIKE %gmail.com;
SELECT * FROM users WHERE p…关注我们,设为星标,每天7:30不见不散,每日java干货分享你接到了一个运营需求“帮我导出所有Gmail 邮箱的用户” 或者 “查一下所有尾号是 1234的手机号”。直觉写法SELECT * FROM users WHERE email LIKE %gmail.com; SELECT * FROM users WHERE phone LIKE %1234;结果只要数据量上了百万级这两条 SQL 就会变成“慢查询”。因为%在最左边B 树索引无法从左向右匹配只能被迫全表扫描 (Full Table Scan)。解决方案既然数据库只擅长“从左往右”查那我们就把数据**“倒着存”**强行让它变成前缀匹配1. 核心原理把“后缀”变成“前缀”B 树索引是按照字典序从左到右排列的。• 正序apple,banana,cherry...• 我们要查以e结尾的单词索引帮不上忙因为e在单词末尾。反向存储的思想如果我们把字符串翻转存入数据库•elppa(apple)•ananab(banana)•yrrehc(cherry)现在我们要查以e结尾的单词就变成了查以e开头的反向单词。即LIKE e%。这时索引就生效了2. 实战演练MySQL 5.7 的优雅实现在旧版本中我们需要在应用层Java/Python先把字符串反转再存入一个物理列reverse_email。这很麻烦还需要维护数据一致性。MySQL 5.7 引入的“虚拟生成列” (Generated Columns)让这一切变得极其优雅。我们不需要修改业务代码插入逻辑全靠数据库自动完成。步骤 A原始表结构CREATE TABLE users ( id INT PRIMARY KEY, email VARCHAR(100), phone VARCHAR(20) -- 索引加在 email 上也没用因为我们要查后缀 );步骤 B添加虚拟列并建立索引我们创建一个虚拟列email_reverse它的值永远等于REVERSE(email)并给它加索引。-- 1. 添加虚拟列 (Virtual Column) -- 这一步不占存储空间只是定义计算逻辑 ALTER TABLE users ADD COLUMN email_reverse VARCHAR(100) GENERATED ALWAYS AS (REVERSE(email)) VIRTUAL; -- 2. 给虚拟列加索引 (索引是占物理空间的) CREATE INDEX idx_email_reverse ON users(email_reverse);步骤 C修改查询 SQL现在当我们需要查gmail.com时我们在 SQL 里把关键词也反转一下。优化前 (全表扫描 ):SELECT * FROM users WHERE email LIKE %gmail.com;优化后 (走索引 ):-- 搜索词从 gmail.com 变成 moc.liamg SELECT * FROM users WHERE email_reverse LIKE moc.liamg%;Explain 效果type从ALL变成了rangekey使用了idx_email_reverse。查询速度瞬间从秒级变成毫秒级。3. 四大实战场景这个技巧专注于解决“左模糊匹配” (Suffix Match)的痛点。场景一手机号/身份证号后几位搜索需求客服系统用户来电验证身份只报出了手机号最后 4 位 “8888”。•传统LIKE %8888(慢)•优化存一个reverse_phone虚拟列。•查询reverse_phone LIKE 8888%(快)场景二邮箱域名统计/筛选需求找出所有使用公司企业邮箱 (company.com) 的注册用户。•优化对邮箱进行反向索引。这比使用全文检索 (Full Text Search) 更轻量且实时性更好。场景三文件扩展名检索需求网盘系统用户想筛选所有.jpg或.docx文件。•文件名2024_report.docx•反向名xcod.troper_4202•查询reverse_name LIKE xcod.%场景四车牌号限行查询需求交通系统需要找出所有尾号是1或6的车辆进行限行抓拍。• 车牌号的尾号在字符串最后反向存储后尾号变成了“头号”查询效率极高。4. 局限性与避坑虽然“反向存储”很好用但它不是万能的。1.只解决“后缀”查询它只能解决LIKE %abc。如果你需要LIKE %abc%(中间包含)反向存储也无能为力。中间包含的查询只能靠Elasticsearch (ES)或 MySQL 的全文索引 (Full-Text Index)。2.写操作开销虽然虚拟列VIRTUAL不占数据行空间但索引是实实在在的。每次插入或更新email数据库都要计算反转值并更新 B 树索引会稍微增加写操作的负担。3.SQL 可读性开发人员维护 SQL 时看到moc.liamg可能会懵逼。建议在 DAO 层封装好工具类或者在 SQL 注释里写清楚。5. 总结当遇到“查屁股”后缀匹配的需求时不要直接上 ES也不要忍受全表扫描。MySQL 虚拟列 REVERSE 函数 索引就是性价比最高的解决方案。它用极小的成本换来了极致的查询性能。推荐阅读 点击标题可跳转50个Java代码示例全面掌握Lambda表达式与Stream API16 个 Java 代码“痛点”大改造“一般写法” VS “高级写法”终极对决看完代码质量飙升为什么高级 Java 开发工程师喜爱用策略模式精选Java代码片段覆盖10个常见编程场景的更优写法提升Java代码可靠性5个异常处理最佳实践为什么大佬的代码中几乎看不到 if-else因为他们都用这个...还在 Service 里疯狂注入其他 Service你早就该用 Spring 的事件机制了看完本文有收获请转发分享给更多人关注「java干货」加星标提升java技能❤️给个「推荐 」是最大的支持❤️.cls-1{fill:#001e36;}.cls-2{fill:#31a8ff;}.cls-1{fill:#001e36;}.cls-2{fill:#31a8ff;}.cls-1{fill:#001e36;}.cls-2{fill:#31a8ff;}