You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MySQL 8中存储phash并计算汉明距离以查找相似图片

问题根因

你当前的方案确实存在字段类型选择错误、运算逻辑不兼容两个核心问题:

  • 首先varchar类型存储的十六进制字符串不能直接参与位运算,你手动拼接0x前缀本质还是字符串,MySQL不会自动识别为数值类型参与异或计算
  • 64位的phash本身是8字节的无符号整数,用varchar存储不仅浪费存储空间,还无法直接使用MySQL内置的位运算函数,查询效率极低,全表扫描场景下数据量过万就会有明显卡顿。

修复方案

第一步:调整字段类型

可以二选一:

  1. 优先选择BIGINT UNSIGNED类型存储phash,刚好匹配64位phash的长度,位运算效率最高。
  2. 如果要兼容多长度哈希,也可以用BINARY(8)类型存储,不过位运算需要额外转换,优先推荐第一种方案。

第二步:调整写入和查询逻辑

  • Python写入前把十六进制字符串转成整数再入库:
response2 = requests.get(url, stream=True)
if response2:
    response2.raw.decode_content = True
    image2 = Image.open(response2.raw)
    hash2 = str(imagehash.phash(image2))
    # 转成64位无符号整数再插入数据库
    hash_int = int(hash2, 16)
  • 查询语句直接用整数做异或运算即可:
SELECT m.*,
       BIT_COUNT( 0xae95916ec1354a9d ^ m.hash_int) as hd
from media m
where m.hash_int is not null
ORDER BY hd ASC;

如果暂时不想改现有字段结构,也可以用UNHEX函数把十六进制字符串转成二进制再计算汉明距离,注意要处理好64位对齐:

SELECT m.*,
       BIT_COUNT( CAST(UNHEX('ae95916ec1354a9d') AS UNSIGNED) ^ CAST(UNHEX(m.HASH) AS UNSIGNED)) as hd
from media m
where m.HASH is not null
ORDER BY hd ASC;

注意:临时兼容方案性能比改字段类型差很多,仅适合小数据量测试用,生产环境务必调整字段类型。

内容的提问来源于stack exchange,提问作者merlin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 05:48:03