1. 为什么LIKE %abc查询会慢到哭当我们在MySQL中执行LIKE %abc这样的查询时数据库引擎无法利用B树索引的有序特性。这是因为索引的最左匹配原则B树索引是按照字段值的从左到右顺序构建的。当查询条件是LIKE abc%时可以利用索引快速定位到以abc开头的记录但当使用LIKE %abc时由于通配符在最前面索引完全失效。全表扫描不可避免MySQL不得不扫描表中的每一行数据检查字段值是否以abc结尾。对于大表来说这种操作的成本是O(n)级别的。隐式类型转换的陷阱如果字段类型与查询条件类型不匹配如字段是varchar但传入了数字还会导致额外的类型转换开销。实测案例在一个包含1000万条用户评论的表中LIKE %好评查询耗时8.3秒而LIKE 好评%仅需0.02秒性能相差415倍2. 反向存储大法的实现原理2.1 核心思路空间换时间反向存储法的本质是通过预先计算将数据以更适合查询的方式存储创建新列存储字段的反向值如hello存为olleh对该列建立普通B树索引查询时使用LIKE cba%替代LIKE %abc-- 创建反向存储列 ALTER TABLE products ADD COLUMN name_reverse VARCHAR(255); UPDATE products SET name_reverse REVERSE(name); -- 建立索引 CREATE INDEX idx_name_reverse ON products(name_reverse); -- 查询优化 SELECT * FROM products WHERE name_reverse LIKE cba%;2.2 虚拟生成列的妙用MySQL 5.7支持生成列(GENERATED COLUMN)可以自动维护反向值ALTER TABLE products ADD COLUMN name_reverse VARCHAR(255) GENERATED ALWAYS AS (REVERSE(name)) STORED;这种方式相比触发器更轻量且保证数据一致性。STORED表示实际存储占用空间VIRTUAL则表示动态计算不占空间但查询时计算。3. 完整实施方案与性能对比3.1 四步落地方案评估阶段使用EXPLAIN分析原查询执行计划统计LIKE %abc查询的频率和响应时间实施阶段-- 方案A普通列触发器 ALTER TABLE orders ADD COLUMN comment_reverse VARCHAR(500); CREATE TRIGGER trg_reverse_comment BEFORE INSERT ON orders FOR EACH ROW SET NEW.comment_reverse REVERSE(NEW.comment); -- 方案B生成列MySQL 5.7 ALTER TABLE orders ADD COLUMN comment_reverse VARCHAR(500) GENERATED ALWAYS AS (REVERSE(comment)) STORED;索引优化CREATE INDEX idx_comment_reverse ON orders(comment_reverse); ANALYZE TABLE orders;查询改造-- 原查询 SELECT * FROM orders WHERE comment LIKE %质量好%; -- 优化后 SELECT * FROM orders WHERE comment_reverse LIKE 好量质%;3.2 性能实测数据数据量查询类型平均耗时(ms)扫描行数10万LIKE %abc120010000010万反向LIKE cba%15231000万LIKE %abc9800100000001000万反向LIKE cba%1831在千万级数据量下性能提升达到544倍。索引命中后扫描行数从全表降至个位数。4. 进阶优化与边界场景4.1 多条件组合查询当需要同时匹配前缀和后缀时可以组合使用正向和反向索引-- 查找name以A开头且以z结尾的记录 SELECT * FROM products WHERE name LIKE A% AND name_reverse LIKE z%;4.2 中文分词场景处理对于中文文本建议结合全文索引-- 创建全文索引 ALTER TABLE articles ADD FULLTEXT INDEX ft_idx_content(content); -- 组合查询 SELECT * FROM articles WHERE MATCH(content) AGAINST(性能优化) AND content_reverse LIKE 化优能性%;4.3 注意事项与局限性存储成本反向列会占用额外存储空间需评估存储性价比写入性能触发器或生成列会增加约5%-10%的写入开销排序问题ORDER BY需要特别注意-- 错误写法按反向值排序 SELECT * FROM products WHERE name_reverse LIKE cba% ORDER BY name_reverse; -- 正确写法 SELECT * FROM products WHERE name_reverse LIKE cba% ORDER BY name;模糊程度LIKE %a%b%c%这类多通配符查询仍需全表扫描5. 替代方案横向对比方案优点缺点适用场景反向存储性能提升显著兼容性好需要额外存储空间固定后缀查询全文索引支持语义搜索配置复杂占用资源多文本内容搜索搜索引擎专业检索能力系统复杂度高海量文本搜索函数索引无需冗余存储仅部分数据库支持PostgreSQL/Oracle在MySQL环境中对于确定的尾部匹配模式反向存储法仍是性价比最高的方案。PostgreSQL用户可以考虑函数索引-- PostgreSQL函数索引 CREATE INDEX idx_product_name_reverse ON products(REVERSE(name));这个方案不需要额外存储列但MySQL目前不支持函数索引8.0支持表达式索引但性能不如物化列。
阅读完成 · 觉得有帮助?