手机号变成密文,如何模糊搜索
密文搜索问题,用空间换时间,方案:
(1)分词,以手机号举例,按固定长度切,比如四位一段什么1381 3812 8123;
(2)每一段单独用哈希算法算成短码;
(3)用特殊分隔符把这些短码拼接成一个字符串;
索引字段可能会比原来的字段还要长,存储会变大,第二搜索粒度是固定的,按四位切,用户搜3位就肯定查不到,第三个like前面带百分比索引会失效,全表扫描,数据量大的时候会消耗性能。实际业务只需要支持后四位的查询,切片策略是可以灵活调整。甚至like前面的百分号,也是可以优化掉的,这个要看具体需求。
AI回答:
这是针对加密敏感字段的高效模糊搜索场景的经典方案,核心思想是分词哈希索引 + 空间换时间,解决「加密字段直接用 like 模糊查询导致全表扫描、性能极差」的痛点,同时全程不泄露明文,满足数据安全合规要求。
一、核心实现步骤
以手机号加密字段的模糊搜索为例,整体分为三步:
1. 固定步长滑动分词(N-gram 切片)
对明文敏感字段做固定长度的滑动窗口切片,比如采用 4 位一组(4-gram):
- 例如手机号
13812345678,会生成1381、3812、8123、1234、2345、3456、4567、5678共 8 个连续分片。 - 滑动分词的目的是支持任意位置的模糊匹配;如果业务只需要支持后四位查询,可以只截取尾部固定片段,无需全量滑动。
2. 分片哈希脱敏
对每一个明文分片单独做哈希运算(可搭配随机盐进一步提升安全性),生成固定长度的哈希短码。
- 核心作用:避免明文分片直接存储导致的数据泄露,保证索引字段全程为密文形态,符合数据安全规范。
3. 拼接构建索引字段
用固定分隔符将所有分片的哈希短码拼接成一个完整字符串,作为独立的索引字段存入数据库,并对该字段建立普通 B+ 树索引。
- 查询时,对用户输入的关键词执行完全相同的「分词 → 哈希」处理,生成查询片段,再去匹配索引字段。
二、方案的核心权衡:空间换时间
- 收益:把原本对密文的全表扫描,转化为对索引字段的匹配查询,性能提升 1~2 个数量级;全程不暴露原始明文,满足等保、数据安全合规要求。
- 代价:索引字段会比原加密字段体积更大,存储成本上升,是典型的空间换时间思路。
三、固有局限与针对性优化
这个方案存在三个经典问题,都可以结合业务场景做定向优化:
1. 局限:存储膨胀,索引字段比原字段更长
全量滑动分词会生成大量分片,索引字段长度远超原加密字段,存储开销高。
- 优化:根据业务需求收缩分词范围。比如业务明确只需要查手机号后 4 位,就只对尾部固定长度切片,不用全量滑动,分片数量从 8 个降到 1 个,存储开销大幅下降。
2. 局限:搜索粒度固定,短查询无法命中
分词长度决定了最小匹配粒度,比如按 4 位分词,用户只输入 3 位就无法匹配命中。
- 优化:根据业务最小查询粒度调整分词长度。比如业务要求支持 3 位模糊查询,就调整为 3-gram;在存储成本和查询粒度之间做权衡,业务边界越清晰,优化效果越好。
3. 局限:前后模糊匹配导致索引失效
如果用 %xxx% 全模糊匹配,会导致 B+ 树索引失效,退化为全表扫描,数据量大时性能损耗严重。
- 优化:结合业务场景把模糊匹配转化为前缀匹配。
- 比如业务只做后缀匹配(查手机号后四位):可以把分片哈希倒序存储,查询时也对关键词做倒序处理,把后缀匹配转化为前缀匹配,去掉前面的百分号,就能完美命中索引。
- 如果是任意位置匹配,也可以拆分为前缀、后缀多套索引分别构建,根据业务优先级取舍。
四、适用场景与总结
- 适合场景:手机号、身份证号、银行卡号等加密敏感字段,需要支持固定模式的模糊查询,同时对查询性能有要求的业务。
- 核心思路:不追求绝对通用的全模糊匹配,而是基于业务边界做定向优化,在安全、性能、存储三者之间找到最优平衡点,这也是密文搜索方案的核心设计原则。

浙公网安备 33010602011771号