[Clickhouse] ๋ฒกํ„ฐ ๊ฒ€์ƒ‰ (Vector Search)

clickhouse๋Š” ์ž์ฒด์ ์œผ๋กœ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์„ ์œ„ํ•œ ํ•จ์ˆ˜๋“ค์„ ์ œ๊ณตํ•œ๋‹ค.
๋ฌผ๋ก  ์ „๋ฌธ ๋ฒกํ„ฐ DB๋“ค์ฒ˜๋Ÿผ ๋†’์€ ์ฝ๊ธฐ ์ฒ˜๋ฆฌ๋Ÿ‰๊ณผ ๋ ˆ์ดํ„ด์‹œ ๋ณด์žฅ์„ ์ œ๊ณตํ•˜๋Š”๊ฑด ์•„๋‹ˆ๋ผ์„œ, ์‹ค์‹œ๊ฐ„ ์„œ๋น„์Šค์šฉ์œผ๋กœ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

ํ•˜์ง€๋งŒ ๋ฐ์ดํ„ฐ์…‹์ด ์—„์ฒญ๋‚˜๊ฒŒ ํฌ์ง„ ์•Š๊ณ  ๊ธฐ์กด ๋ฐ์ดํ„ฐ์…‹์ด clickhouse์— ์žˆ๋‹ค๋ฉด, ์‹คํ—˜-๊ฒ€์ฆ์šฉ์œผ๋กœ ๊ฐ€๋ณ๊ฒŒ ์“ฐ๊ธฐ์—๋Š” ์ถฉ๋ถ„ํ•˜๋‹ค.

clickhouse๋Š” ์ธ๋ฑ์Šค๋ฅผ ์“ฐ์ง€ ์•Š๋Š” ์ •ํ™•ํ•œ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰๊ณผ, ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ค์ฐจ ์žˆ๋Š” ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์„ ์ œ๊ณตํ•œ๋‹ค.




๋ฒกํ„ฐ ์œ ์‚ฌ๋„ ํ•จ์ˆ˜์™€ ์ •ํ™•ํ•œ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰

clickhouse๋Š” ํ•จ์ˆ˜์˜ ํ˜•ํƒœ๋กœ ์œ ์‚ฌ๋„ ์—ฐ์‚ฐ์„ ์ œ๊ณตํ•œ๋‹ค. ๋”ฐ๋กœ ๋ญ˜ ์„ค์น˜ํ•  ํ•„์š”๋Š” ์—†๋‹ค.

select 
cosineDistance(  
   [0.5736801028251648, 0.2516217529773712, -0.6825592517852783],
   [0.5636801028251648, 0.3516217529773712, -0.16825592517852783]
) as cosine, 
dotProduct(  
   [0.5736801028251648, 0.2516217529773712, -0.6825592517852783],
   [0.5636801028251648, 0.3516217529773712, -0.16825592517852783]
) as dot, 
L2Distance(  
   [1, 2, 3], 
   [2, 3, 4]
) as euclid

๊ทธ๋ƒฅ ์ด๋ ‡๊ฒŒ ๋ฒกํ„ฐ๊ฐ’ 2๊ฐœ ๋„ฃ์œผ๋ฉด ๋น„๊ตํ•ด์ฃผ๋Š” ์‹์ด๋‹ค.

์ •ํ™•ํ•œ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„, ์ € ์œ ์‚ฌ๋„ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ๋‹ค๊ฐ€ ์ •๋ ฌ์— ๋ถ™์ด๋Š” ๊ฒƒ์—์„œ ๋ฒ—์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.
๊ฐ„๋‹จํ•˜๋‹ค.

create table default.vector_test (
  id String, -- uuidv7
	color String, -- Red, Blue, Yellow, Black, White, Green
	vector Array(Float) -- 256 vector
) 
Engine = MergeTree
Order by id

๊ทธ๋ƒฅ ์ ๋‹นํžˆ ๋ฒกํ„ฐ ์ €์žฅ์šฉ ์ปฌ๋Ÿผ ์ถ”๊ฐ€ํ•œ ๋‹ค์Œ์—


INSERT INTO default.vector_test
SELECT 
    generateUUIDv7() as id,
    ['Red', 'Blue', 'Yellow', 'Black', 'White', 'Green'][toUInt8(rand() % 6) + 1] as color,
    arrayMap(x -> randNormal(0.5, 0.3), range(256)) as vector
FROM numbers(5000000)
SETTINGS max_insert_threads=4;

๋ฒกํ„ฐ ๊ฐ’ ๋„ฃ์–ด์ฃผ๊ณ 


select * 
from ํ…Œ์ด๋ธ”
where ... 
order by 
L2Distance(  
   vector, 
   [2, 3, 4, ...]
) asc

์ด๋Ÿฐ ์‹์œผ๋กœ, Distance ๊ฒฐ๊ณผ๋กœ ์ •๋ ฌ์„ ๊ฑธ๋ฉด ๋œ๋‹ค. l2์€ ์ž‘์„์ˆ˜๋ก ๊ฐ€๊นŒ์šฐ๋‹ˆ asc๋ฅผ ๊ฑธ๊ณ , dot/cosine์€ ํด์ˆ˜๋ก ๊ฐ€๊นŒ์šด ๊ฒƒ์ด๋‹ˆ desc๋ฅผ ๊ฑธ๋ฉด ๋˜๊ฒ ๋‹ค.


๊ทธ๋Ÿผ ์ด๋Ÿฐ ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. ํ’€์Šค์บ” ๊ธฐ๋ฐ˜์ด๊ธด ํ•˜์ง€๋งŒ, clickhouse ์ž์ฒด๊ฐ€ ์›Œ๋‚™ ์ด๋Ÿฐ ๋ถ€๋ถ„์— ์ตœ์ ํ™”๊ฐ€ ์ž˜ ๋˜์–ด์žˆ๋‹ค๋ณด๋‹ˆ ์ธ๋ฑ์Šค ์—†์ด ๋Œ์•„๋„ ์–ด์ง€๊ฐ„ํ•œ ์‚ฌ์ด์ฆˆ์—์„œ๋Š” ์ถฉ๋ถ„ํžˆ ๋น ๋ฅด๋‹ค.




์ •ํ™•ํ•œ ๊ฒ€์ƒ‰์˜ ๋ฌธ์ œ

์ € ์ •ํ™•ํ•œ ๊ฒ€์ƒ‰์˜ ๋‹จ์ ์€, ๋ฐ์ดํ„ฐ ํฌ๊ธฐ๊ฐ€ ๋น„๋Œ€ํ•ด์งˆ์ˆ˜๋ก ์„ฑ๋Šฅ ๋ถ€ํ•˜๊ฐ€ ๋ง‰์‹ฌํ•ด์ง„๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ํ•ญ์ƒ ํ’€์Šค์บ”ํ•ด์„œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ๋ฒกํ„ฐ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ๋ฐฉ์‹์€ ํ•˜๋“œ์›จ์–ด๊ฐ€ ์•„๋ฌด๋ฆฌ ์ข‹๋”๋ผ๋„ ๊ทœ๋ชจ ํ™•์žฅ์— ๋”ฐ๋ผ ํ•œ๊ณ„์— ๋ถ€๋”ชํžˆ๊ฒŒ ๋œ๋‹ค.

๋‚ด ๊ฒฝ์šฐ์—๋„ 100-500๋งŒ๊ฐœ ์ •๋„์—์„œ๋Š” ์ˆ˜์›”ํ•˜๊ฒŒ ์ž˜ ๋Œ์•˜์ง€๋งŒ, 2000๋งŒ๊ฐœ์ฏค ๋˜๋‹ˆ ๊ฑฐ์˜ 10์ดˆ ๊ฐ€๊นŒ์ด ๊ฑธ๋ ธ๋‹ค.




๋ฒกํ„ฐ ์ธ๋ฑ์Šค์™€ ๊ทผ์‚ฌ์น˜ ๊ฒ€์ƒ‰

๋‹คํ–‰ํžˆ clickhouse๋Š” HNSW ๋ฒกํ„ฐ ์ธ๋ฑ์Šค ๊ธฐ๋ฐ˜์˜ ๊ทผ์‚ฌ์น˜ ๊ฒ€์ƒ‰ ๋˜ํ•œ ์ œ๊ณตํ•œ๋‹ค.
์™„์ „ํžˆ ์ผ์น˜ํ•˜์ง€๋Š” ์•Š์ง€๋งŒ, ๊ทธ ๋Œ€๊ฐ€๋กœ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ธ ๋ถ€๋ถ„๊ฒ€์ƒ‰์„ ๊ฐ€๋Šฅ์ผ€ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด ๊ธฐ๋Šฅ์€ ์•ˆ์ •ํ™”๋˜์ง€ ์•Š์•˜๊ณ , ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์ด ์ œ๋ฒ• ๋งŽ๋‹ค.
ํ˜„์žฌ 25 ๋ฒ„์ „ ๊ธฐ์ค€์œผ๋กœ๋„ ๋ฒ ํƒ€ ๋ฒ„์ „ ์ƒํƒœ์— ์žˆ๋‹ค.

์•„๋ฌดํŠผ, ์ € ์œ ํด๋ฆฌ๋“œ ๋ฒกํ„ฐ์— ๋Œ€ํ•ด ์ธ๋ฑ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์ด๋Ÿฐ ์‹์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋‹ค.

SET allow_experimental_vector_similarity_index=true;

ALTER TABLE default.vector_test
ADD INDEX vector_index vector TYPE vector_similarity('hnsw', L2Distance, 'f64', 0, 0);

vector_similarity์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” DB ๋ฒ„์ „์— ๋”ฐ๋ผ ์ •์‹ ์—†์ด ๊ณ„์† ๋ฐ”๋€๋‹ค. ์–ด๋–ค ๋ฒ„์ „์—์„œ๋Š” ์ฐจ์›์„ ๋ฐ›๊ธฐ๋„ ํ•˜๊ณ  ์•ˆ๋ฐ›๊ธฐ๋„ ํ•˜๊ณ , ๋งค๊ฐœ๋ณ€์ˆ˜ ์ˆซ์ž๋„ ์™€๋ฆฌ๊ฐ€๋ฆฌํ•œ๋‹ค. ๋ฌธ์„œ๋ฅผ ๋ณด๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค.

์•„๋ฌดํŠผ ๋งŒ๋“ค๊ณ  ๋‚˜๋ฉด ์ธ๋ฑ์Šค๊ฐ€ ์ ์šฉ์ด ๋ ํ…๋ฐ...

์‚ฌ์‹ค ์ž˜ ๋˜์ง„ ์•Š๋Š”๋‹ค.

clickhouse์˜ vector index๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ์ˆœ์ง„ํ•œ ํ˜•ํƒœ๋กœ ๊ตฌํ˜„๋œ ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
์ด ๋ฒกํ„ฐ ์ธ๋ฑ์Šค๋Š” ๋‹ค๋ฅธ ์ธ๋ฑ์Šค๋“ค๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ SKIP Index ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„๋œ๋‹ค. ์ž˜ ๋ชจ๋ฅธ๋‹ค๋ฉด ์ด์— ๋Œ€ํ•œ ๊ตฌ์กฐ ์ดํ•ด๊ฐ€ ์„ ํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค.
https://blog.naver.com/sssang97/223926075870
์•„๋ฌดํŠผ ์ค‘์š”ํ•œ ๊ฒƒ์€, ๋ฒกํ„ฐ ์ธ๋ฑ์Šค๋Š” ํ–‰ ๋‹จ์œ„๊ฐ€ ์•„๋‹ˆ๋ผ granule ๋‹จ์œ„์˜ ์• ๋งคํ•œ ์ธ๋ฑ์Šค ๋‹จ์œ„๋ผ๋Š” ๊ฒƒ์ด๋‹ค.
๊ทธ๋ž˜์„œ ์ด๊ฒƒ๋„ ์ผ์น˜ํ•˜๋Š” ๋ธ”๋ก์„ ์ฐพ์•„๋‚ด๋Š” ์ธ๋ฑ์Šค๊ฐ€ ์•„๋‹ˆ๋ผ, ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๋ธ”๋ก์„ ๋ฒ„๋ฆฌ๋Š” ์ธ๋ฑ์Šค๋กœ ๊ตฌํ˜„๋œ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ณด๋‹ˆ ์ด๊ฑด ํ•ญ์ƒ ํšจ์œจ์ ์ด์ง„ ์•Š์•„์„œ DB๊ฐ€ ๋ฒกํ„ฐ ์ธ๋ฑ์Šค๋ฅผ ์„ ํƒํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋‹ค. ๊ธฐ์กด ๋ฐฉ์‹๋Œ€๋กœ ์Šค์บ”ํ•˜๋Š”๊ฒŒ ์œ ๋ฆฌํ•˜๋‹ค ํŒ๋‹จํ•˜๋ฉด ๊ณผ๊ฐํ•˜๊ฒŒ ๋ฒ„๋ฆฌ๊ณ  ์“ฐ์ง€ ์•Š๋Š”๋‹ค.

EXPLAIN์„ ๊ฑธ์–ด๋ณด๋ฉด, ์ธ๋ฑ์Šค๋ฅผ ์–ด๋–ป๊ฒŒ ํƒ€๋Š”์ง€๋ฅผ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋‚ด ๊ฒฝ์šฐ์—๋Š” ์Šคํ‚ตํ•œ ๋น„์œจ์ด ๋†’์ง€ ์•Š์•„์„œ ์“ฐ๋‹ˆ๋งˆ๋‹ˆํ•œ ๊ตฌ์„ฑ์ด ๋˜์–ด๋ฒ„๋ฆฐ ์ƒํ™ฉ์ด๊ธด ํ•˜๋‹ค.




์‚ฌ์ „ ํ•„ํ„ฐ๋ง๊ณผ ์‚ฌํ›„ ํ•„ํ„ฐ๋ง

๋ฒกํ„ฐ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ• ๋•Œ ๊ฐ€์žฅ ๊ณจ์น˜์•„ํ”ˆ ๋ถ€๋ถ„ ์ค‘ ํ•˜๋‚˜๊ฐ€ ํ•„ํ„ฐ๋ง์ด๋‹ค. ๋ฒกํ„ฐ ์ธ๋ฑ์Šค์˜ ๊ตฌ์กฐ์ƒ ์‚ฌ์ „ ํ•„ํ„ฐ๋ง์˜ ๊ตฌํ˜„์—๋Š” ์ƒ๋‹นํ•œ tradeoff๊ฐ€ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์‚ฌํ›„ ํ•„ํ„ฐ๋ง์€ ์‰ฝ๋‹ค. 100๊ฐœ ๊ฐ€์ ธ์˜ค๋ฉด ๊ทธ ์ค‘์— ๋งž์ง€ ์•Š๋Š” ํ•„ํ„ฐ๋ง ์กฐ๊ฑด์— ๋งž์ง€ ์•Š๋Š” 20๊ฐœ(์˜ˆ์‹œ)๋ฅผ ๋ฒ„๋ฆฌ๊ณ  80๊ฐœ๋งŒ ๋˜์ ธ์ฃผ๋ฉด ๋˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

clickhouse์˜ ํ•„ํ„ฐ๋ง ๋™์ž‘์€ ์ข€ ๋ฏธ๋ฌ˜ํ•œ ๋ถ€๋ถ„์ด ์žˆ๋‹ค. ๋ช…์‹œ์ ์ด์ง€ ์•Š๊ณ , ํ˜„์žฌ ํ…Œ์ด๋ธ” ์ƒํƒœ์— ๋”ฐ๋ผ์„œ ์‚ฌ์ „/์‚ฌํ›„ ํ•„ํ„ฐ๋ง์„ ์ž๋™์œผ๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. (๋‚˜์ค‘์— ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ)

๋งŒ์•ฝ ํ•„ํ„ฐ๋ง ์กฐ๊ฑด์— ์‚ฌ์šฉ๋˜๋Š” ๊ฐ’์ด ๊ธฐ๋ณธํ‚ค, ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ํŒŒํ‹ฐ์…˜ ํ‚ค์˜ ์ผ๋ถ€๋ผ๋ฉด, ๊ทธ๊ฑด ์‚ฌ์ „ ํ•„ํ„ฐ๋ง์ด ๋  ์ˆ˜ ์žˆ๋‹ค.
ํ•„ํ„ฐ๋ง์œผ๋กœ ๊ฑฐ๋ฅธ ๋‹ค์Œ์— ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
๋ฐ˜๋ฉด ํ•„ํ„ฐ๋ง ์กฐ๊ฑด์— ์‚ฌ์šฉ๋˜๋Š” ํ•„๋“œ๊ฐ€ Skip Index์— ๊ฑธ๋ ค์žˆ๊ฑฐ๋‚˜, ์•„๋ฌด๊ฒƒ๋„ ์—†๋‹ค๋ฉด ๊ทธ๊ฑด ์‚ฌํ›„ ํ•„ํ„ฐ๋ง์„ ์„ ํƒํ•œ๋‹ค.

๊ด€๋ จ๋œ ํ”Œ๋ž˜๊ทธ๋Š” vector_search_filter_strategy์ด๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ auto๋ผ์„œ ์ž๋™์œผ๋กœ ํ•„ํ„ฐ๋ง ๋ฐฉ์‹์„ ์„ ํƒํ•œ๋‹ค.

๊ทธ๋ž˜์„œ ๊ธฐ๋ณธํ‚ค๋กœ ์ธ๋ฑ์Šค๋ฅผ ๊ฑธ์–ด๋ณด๋ฉด

์‹ค์ œ๋กœ 999๊ฐœ๋ฅผ ์Šค์บ”ํ•ด์™€์„œ 999๊ฐœ์— ๋Œ€ํ•ด์„œ๋งŒ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.



์ฐธ์กฐ
https://clickhouse.com/docs/knowledgebase/vector-search
https://clickhouse.com/docs/engines/table-engines/mergetree-family/annindexes
https://clickhouse.com/docs/sql-reference/functions/distance-functions
https://clickhouse.com/docs/operations/settings/settings#vector_search_filter_strategy