Каков наиболее эффективный способ найти эвклидовое расстояние в 3d с помощью mysql?
У меня есть таблица MySQL с тысячами точек данных, хранящихся в 3 столбцах R, G, B. Как я могу найти, какая точка данных ближе всего к данной точке (a, b, c), используя евклидово расстояние?
Я сохраняю RGB-значения цветов отдельно в таблице, поэтому значения ограничены 0-255 в каждом столбце. То, что я пытаюсь сделать, - найти ближайшую совпадение цвета, найдя цвет с наименьшим эвклидовым расстоянием.
Я мог бы явно пробежать каждую точку таблицы, чтобы вычислить расстояние, но это не было бы достаточно эффективным для масштабирования. Любые идеи?
Ответы
Ответ 1
- Поскольку вы ищете минимальное расстояние, а не точное расстояние, вы можете пропустить квадратный корень. Я думаю, Квадратное Евклидово расстояние здесь.
- Вы сказали, что значения ограничены между 0-255, поэтому вы можете сделать индексную таблицу поиска с 255 значениями.
Вот что я думаю в терминах SQL. r0
, g0
и b0
представляют целевой цвет. Таблица Vector
будет содержать квадратные значения, упомянутые выше в # 2. Это решение будет посещать все записи, но набор результатов может быть установлен в 1 путем сортировки и выбора только первой строки.
select
c.r, c.g, c.b,
mR.dist + mG.dist + mB.dist as squared_dist
from
colors c,
vector mR,
vector mG,
vector mB
where
c.r-r0 = mR.point and
c.g-g0 = mG.point and
c.b-b0 = mB.point
group by
c.r, c.g, c.b
Ответ 2
Я думаю, что приведенные выше комментарии верны, но они - по моему скромному мнению - не отвечают на исходный вопрос. (Поправьте меня если я ошибаюсь). Итак, позвольте мне добавить мои 50 центов:
Вы запрашиваете оператор select, который, учитывая, что ваша таблица называется "цветами", и учитывая, что ваши столбцы называются r, g и b, они являются целыми числами в диапазоне 0..255, и вы ищете значение, в вашей таблице, ближе всего к заданному значению, скажем: rr, gg, bb, тогда я бы осмелился попробовать следующее:
select min(sqrt((rr-r)*(rr-r)+(gg-g)*(gg-g)+(bb-b)*(bb-b))) from colors;
Теперь этот ответ дается с большим количеством оговорок, так как я не уверен, что правильно ответил на ваш вопрос, поэтому подтвердите, правильно ли это, или исправьте меня, чтобы я мог помочь.
Ответ 3
Первый уровень оптимизации, который, как я вижу, вы можете сделать, будет равен расстоянию, на которое вы хотите ограничить запрос, чтобы вам не нужно было выполнять квадратный корень для каждой строки.
Второй уровень оптимизации, который я бы рекомендовал, - это некоторая предварительная обработка, чтобы облегчить необходимость постороннего возведения в квадрат для каждого запроса (что могло бы создать некоторое дополнительное время выполнения для больших таблиц RGB). Вам нужно будет выполнить некоторый бенчмаркинг, но, заменив значения для a, b, c и d, а затем выполнив запрос, вы можете облегчить стресс от MySQL.
![Latex]()
Обратите внимание, что разница в производительности между двумя последними линиями может быть незначительной. Вам нужно будет использовать тестовые запросы в вашей системе, чтобы определить, что быстрее.
Я просто перечитал и заметил, что вы заказываете дистанцию. В этом случае d следует удалить, все должно быть перемещено в одну сторону. Вы все еще можете подключить константы, чтобы предотвратить дополнительную обработку в конце MySQL.
Ответ 4
Я считаю, что есть два варианта.
Вы должны либо, как вы говорите, перебирать по всему набору, и сравнивать и проверять максимум, который вы задали первоначально, с невероятно низким числом, например -1. Это выполняется в линейном времени, n раз (поскольку вы только сравниваете 1 пункт с каждой точкой набора, это масштабируется линейным образом).
Я все еще думаю о другом варианте... что-то похожее на то, чтобы выполнить первый поиск в стороне от точки ввода до тех пор, пока точка не будет найдена в наборе в искомой точке, но для этого требуется немного больше мысли ( Я полагаю, что 3D-пространство должно быть довольно густо заселено, чтобы это было более эффективным в среднем, хотя).
Ответ 5
Если вы пропустите каждую точку и вычислите расстояние, не используйте функцию квадратного корня, это не обязательно. Наименьшей суммы квадратов будет достаточно.
Это problem, который вы пытаетесь решить. (Planar case, выберите все точки, отсортированные по оси x, y или z, затем используйте PHP для их обработки)
MySQL также имеет