> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL에서 벡터 임베딩 생성하기

> VillageSQL의 ai_embedding() 함수로 MySQL에서 벡터 임베딩을 생성하고 저장하는 방법 — 시맨틱 검색, 유사도 매칭, 추천 시스템을 위해.

> [card] [VillageSQL is a drop-in replacement for MySQL with extensions.](https://villagesql.com/docs/en/8.4/stable/install-server.md)
>
> All examples on this page work on VillageSQL. Install Now →

벡터 임베딩은 텍스트를 의미를 담은 숫자 배열로 나타냅니다. 같은 주제에 대한 두 텍스트는 공유하는 단어가 없어도 비슷한 벡터를 가집니다. MySQL에는 임베딩을 생성하는 내장 방법이 없습니다. VillageSQL의 `vsql_ai` 확장은 `ai_embedding()`을 추가하는데, 이 함수는 임베딩 모델을 호출하고, 저장하고 쿼리할 수 있는 JSON 배열로 벡터를 반환합니다.

## 임베딩의 용도

임베딩 모델은 텍스트를 고정 길이의 실수 벡터로 변환합니다. 두 벡터 사이의 거리는 의미적 유사도를 반영합니다:

* `"dog"`와 `"puppy"` → 비슷한 벡터
* `"dog"`와 `"database index"` → 먼 벡터

이것은 시맨틱 검색(쿼리와 같은 *의미*인 행 찾기), 클러스터링, 추천을 가능하게 합니다. 키워드 검색은 이 중 어느 것도 잘 처리하지 못합니다.

## VillageSQL과 함께: ai\_embedding()

```sql theme={null}
INSTALL EXTENSION vsql_ai;
```

`ai_embedding(provider, model, api_key, text)`는 임베딩 모델을 호출하고 JSON 배열 문자열을 반환합니다.

```sql theme={null}
SET @key = 'your-openai-api-key';

SELECT ai_embedding('openai', 'text-embedding-3-small', @key, 'Machine learning is fascinating');
-- Returns: [0.02646778, 0.019067757, -0.05332306, ...]
```

### 문자 집합 변환

VillageSQL 0.0.6 이하에서 `ai_embedding()`은 binary 문자 집합을 반환하고, MySQL의 JSON 파서는 binary 문자열을 거부합니다. 결과가 `JSON` 열이나 JSON 함수에 도달하기 전에 `CONVERT(... USING utf8mb4)`를 거쳐야 합니다:

```sql theme={null}
-- On 0.0.6 and earlier, this throws an error — JSON_LENGTH rejects binary charset
-- ERROR 3144 (22032): Cannot create a JSON value from a string with CHARACTER SET 'binary'
SELECT JSON_LENGTH(ai_embedding('openai', 'text-embedding-3-small', @key, 'Machine learning'));

-- This works on every version
SELECT JSON_LENGTH(
  CONVERT(ai_embedding('openai', 'text-embedding-3-small', @key, 'Machine learning')
          USING utf8mb4)
);
```

VillageSQL 0.0.7 이상은 올바른 문자 집합을 직접 반환하므로 거기서는 `CONVERT`가 더 이상 필요하지 않습니다. 하지만 남겨 두어도 해가 없으므로, 아래의 모든 예제는 0.0.6 이하와의 호환성을 위해 여전히 사용합니다.

### 임베딩 저장하기

JSON 배열을 `JSON` 열에 저장하세요:

```sql theme={null}
CREATE TABLE documents (
    id       INT AUTO_INCREMENT PRIMARY KEY,
    title    VARCHAR(255),
    content  TEXT,
    embedding JSON
);

SET @key = 'your-openai-api-key';
-- max_execution_time only bounds SELECT statements — it has no effect on
-- this INSERT.

INSERT INTO documents (title, content, embedding) VALUES
    ('Intro to ML',
     'Machine learning is a subset of artificial intelligence',
     CONVERT(ai_embedding('openai', 'text-embedding-3-small', @key,
                          'Machine learning is a subset of artificial intelligence')
             USING utf8mb4)),
    ('Neural Networks',
     'Deep learning uses multi-layer neural networks',
     CONVERT(ai_embedding('openai', 'text-embedding-3-small', @key,
                          'Deep learning uses multi-layer neural networks')
             USING utf8mb4));

-- Confirm the vectors parsed as JSON
SELECT id, JSON_LENGTH(embedding) AS dimensions FROM documents;
```

### 기존 행에 임베딩 채우기

```sql theme={null}
ALTER TABLE documents ADD COLUMN embedding JSON;

SET @key = 'your-openai-api-key';
-- max_execution_time only bounds SELECT statements — it has no effect on
-- this UPDATE. To cap how long it runs, get SELECT CONNECTION_ID() beforehand
-- and run KILL QUERY <id> from another session if it runs too long.

UPDATE documents
SET embedding = CONVERT(ai_embedding('openai', 'text-embedding-3-small', @key, content)
                        USING utf8mb4)
WHERE embedding IS NULL
LIMIT 50;  -- Process in batches
```

## 모델 선택하기

| 제공자 | 모델 | 차원 | 사용 시점 |
| :- | :- | :- | :- |
| `'openai'` | `text-embedding-3-small` | 1536 | 최고의 가성비 — 좋은 정확도, 더 낮은 비용 |
| `'openai'` | `text-embedding-3-large` | 3072 | 더 높은 정확도가 필요할 때 |
| `'google'` | `gemini-embedding-001` | 3072 | Google 생태계 |
| `'local'` | 모든 Ollama 모델(예: `nomic-embed-text`) | 다양함 | 비공개 데이터; API 키 필요 없음 |

테이블의 모든 임베딩에 같은 모델을 사용하세요. 다른 모델의 임베딩은 비교할 수 없습니다. 섞으면 의미 없는 유사도 점수가 나옵니다.

Anthropic은 현재 임베딩 API를 제공하지 않습니다.

## 시맨틱 검색

MySQL도 VillageSQL도 네이티브 벡터 거리 함수를 제공하지 않습니다. 큰 테이블에서 가장 가까운 벡터를 찾는 완전한 유사도 검색은 애플리케이션 코드에서 실행됩니다. 일반적인 아키텍처: 임베딩을 MySQL에 저장하고, 가져오고, 애플리케이션에서 코사인 유사도를 계산하고, 상위 일치를 반환합니다.

```sql theme={null}
-- Generate a query embedding
SET @query_embedding = ai_embedding('openai', 'text-embedding-3-small', @key, 'neural networks');

-- Retrieve stored embeddings to process in application code
SELECT id, title, embedding FROM documents;
```

결과를 벡터 유사도 라이브러리(NumPy, scikit-learn, Faiss)에 넘겨 최근접 이웃을 찾으세요. 프로덕션 규모의 검색에는 MySQL 옆에 전용 벡터 데이터베이스를 고려하세요.

## 무엇을 임베딩할지

임베딩의 품질은 무엇을 임베딩하는지에 달려 있습니다. 몇 가지 패턴:

```sql theme={null}
-- Embed the full content for document search
SET embedding = CONVERT(ai_embedding('openai', 'text-embedding-3-small', @key, content)
                        USING utf8mb4);

-- Embed a specific field for product search
SET embedding = CONVERT(ai_embedding('openai', 'text-embedding-3-small', @key, product_description)
                        USING utf8mb4);

-- Embed concatenated fields for richer context
SET embedding = CONVERT(ai_embedding('openai', 'text-embedding-3-small', @key,
                            CONCAT(product_name, '. ', category, '. ', product_description))
                        USING utf8mb4);
```

임베딩하는 텍스트는 수천 토큰 아래로 유지하세요. 더 긴 텍스트는 임베딩 모델이 잘라냅니다.

## 자주 묻는 질문

#### 다른 모델의 임베딩을 비교할 수 있나요?

아니요. `text-embedding-3-small`과 `gemini-embedding-001`의 임베딩은 서로 다른 벡터 공간에 있습니다. 서로 비교하면 유사도 점수가 의미 없습니다. 열마다 모델 하나로 표준화하세요.

#### 임베딩은 저장 공간을 얼마나 차지하나요?

실수 1536개의 JSON 배열은 텍스트 문자열로 행당 대략 10–15 KB입니다. 큰 테이블에서는 이것이 쌓입니다. 모든 임베딩을 저장해야 하는지, 아니면 쿼리할 것만 저장하면 되는지 고려하세요.

#### ai\_embedding()은 일괄 입력을 지원하나요?

아니요. 각 호출은 텍스트 입력 1개를 처리합니다. 대량 임베딩은 애플리케이션에서 행을 순회하며 `UPDATE`를 배치로 호출하세요.

#### 텍스트가 너무 길면 어떻게 되나요?

임베딩 모델은 토큰 한도(OpenAI 모델은 보통 8191 토큰)에서 입력을 잘라냅니다. 임베딩은 잘린 텍스트로 계산됩니다. 긴 문서는 전체 텍스트 대신 요약이나 첫 몇 문단을 임베딩하세요.

## 문제 해결

| 문제 | 해결 방법 |
| :- | :- |
| `FUNCTION <database>.ai_embedding does not exist` | `INSTALL EXTENSION vsql_ai` 실행 |
| `ERROR 3144: Cannot create a JSON value from a string with CHARACTER SET 'binary'` | 호출을 `CONVERT(... USING utf8mb4)`로 감싸기 — [문자 집합 변환](#the-charset-conversion) 참조 |
| `ai_embedding()`이 NULL을 반환 | API 키 확인; 모델 이름 확인; `max_execution_time` 확인 |
| 유사도 검색이 잘못된 결과를 반환 | 모든 임베딩이 같은 모델을 쓰는지 확인; 검색하는 내용과 다른 내용으로 임베딩이 생성되지 않았는지 확인 |
| 임베딩 생성이 너무 오래 걸림 | LIMIT 배치를 사용; 임베딩은 API 호출당 각각 약 1–3초 |

## 함께 보기

* [MySQL을 AI API에 연결하기](https://villagesql.com/docs/ko/guides/ai-api-setup.md) — vsql\_ai 확장 설치와 구성
* [MySQL 쿼리에서 AI 모델 실행하기](https://villagesql.com/docs/ko/guides/ai-prompts-in-mysql.md) — 임베딩을 보완하는 텍스트 생성
* [MySQL의 UUID](https://villagesql.com/docs/ko/guides/uuids.md) — 임베딩 조회 테이블을 위한 안정적인 행 식별자
* [MySQL의 다차원 범위 쿼리](https://villagesql.com/docs/ko/guides/cube-queries.md) — AI 벡터 없이 하는 기하학적 포함 및 거리 쿼리


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.