我正在创建一个人脸识别系统,但搜索速度很慢。你能分享一下如何加快搜索速度吗?
100,000 个数据项大约需要 6 秒。
mysql> SHOW VARIABLES LIKE '%version%';
+--------------------------+------------------------------+
| Variable_name | Value |
+--------------------------+------------------------------+
| version | 8.0.29 |
| version_comment | MySQL Community Server - GPL |
| version_compile_machine | x86_64 |
| version_compile_os | Linux |
+--------------------------+------------------------------+
CREATE TABLE `face_feature` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`f1` decimal(9,8) NOT NULL,
`f2` decimal(9,8) NOT NULL,
...
...
`f127` decimal(9,8) NOT NULL,
`f128` decimal(9,8) NOT NULL,
PRIMARY KEY (id)
);
mysql> SELECT count(*) FROM face_feature;
+----------+
| count(*) |
+----------+
| 110004 |
+----------+
mysql> SELECT * FROM face_feature LIMIT 1\G;
id: 1
f1: -0.07603023
f2: 0.13605964
...
f127: 0.09608927
f128: 0.00082345
SELECT
id,
sqrt(
power(f1 - (-0.09077361), 2) +
power(f2 - (0.10373443), 2) +
...
...
power(f127 - (0.0778369), 2) +
power(f128 - (0.00951046), 2)
) as distance
FROM
face_feature
ORDER BY
distance
LIMIT
1
;
+----+--------------------+
| id | distance |
+----+--------------------+
| 1 | 0.3376853491771237 |
+----+--------------------+
1 row in set (6.18 sec)
更新1:
从更改decimal(9,8)
为float(9,8)
然后,从改进approximately 4sec
到3.26 sec
mysql> desc face_feature;
+-------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| f1 | float(9,8) | NO | | NULL | |
| f2 | float(9,8) | NO | | NULL | |
..
| f127 | float(9,8) | NO | | NULL | |
| f128 | float(9,8) | NO | | NULL | |
+-------+------------+------+-----+---------+----------------+
更新 2:
从更改POWER(z, 2)
为z*z
然后,结果从更改3.26 sec
为4.65 sec
SELECT
id,
sqrt(
((f1 - (-0.09077361)) * (f1 - (-0.09077361))) +
((f2 - (0.10373443)) * (f2 - (0.10373443))) +
((f3 - (0.00798536)) * (f3 - (0.00798536))) +
...
...
((f126 - (0.07803915)) * (f126 - (0.07803915))) +
((f127 - (0.0778369)) * (f127 - (0.0778369))) +
((f128 - (0.00951046)) * (f128 - (0.00951046))
) as distance
FROM
face_feature
ORDER BY
distance
LIMIT
1
;
更新 3
我正在研究 MySQL GIS 的使用。
如何在 MySQL 中从“float”迁移到“points”?
更新 4
我也在研究 PostgreSQL,因为我找不到在 MySQL 中处理 128 维的方法。
DECIMAL(9,8)
- 这是很多有效数字。你需要那么精确吗?
FLOAT
-- 约 7 位有效数字;更快的算术。
POWER(z, 2)
- 可能比z*z
. (这可能是最慢的部分。)
SQRT
-- 在许多情况下,您可以简单地使用正方形。在这种情况下:
SELECT SQRT(closest)
FROM ( SELECT -- leave out SQRT
... ORDER BY .. LIMIT 1 )
这里有一些其他的想法。它们不一定与正在讨论的查询相关:
精确测试——当心比较“相等”的舍入错误可能会意外地使事情变得不相等。不精确的测量增加了这个问题。如果我测量两次,我可能一次得到 1.23456789,下一次得到 1.23456788。(特别是在那个“精度”级别。
交易复杂性与速度——ABS(a - b)
用作距离公式;以这种方式找到最接近的 10 个项目,然后使用欧几里得距离来获得“正确”的距离。
将面分成多个区域。找出项目所在的区域,然后仅检查该区域中 128 个点的子集。(靠近边界——在两个区域中放置一些点。)
开箱即用——我不熟悉你的面部识别,所以我已经用完了数学技巧。
切换到POINTs
和一个SPATIAL
索引。您的任务可能会更快几个数量级。(这对于 128 维空间可能不实用。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句