VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
vsql_ai extension adds ai_embedding(), which calls an embedding model and returns the vector as a JSON array you can store and query.
What Embeddings Are For
An embedding model converts text to a fixed-length vector of floats. The distance between two vectors reflects semantic similarity:"dog"and"puppy"→ similar vectors"dog"and"database index"→ distant vectors
With VillageSQL: ai_embedding()
ai_embedding(provider, model, api_key, text) calls an embedding model and returns a JSON array string.
Storing embeddings
Store the JSON array in aJSON column:
Backfilling embeddings on existing rows
Choosing a Model
| Provider | Model | Dimensions | Use when |
|---|---|---|---|
'openai' | text-embedding-3-small | 1536 | Best value — good accuracy, lower cost |
'openai' | text-embedding-3-large | 3072 | Higher accuracy needed |
'google' | gemini-embedding-001 | 3072 | Google ecosystem |
'local' | any Ollama model (e.g., nomic-embed-text) | varies | Private data; no API key required |
Semantic Search
Neither MySQL nor VillageSQL provides a native vector distance function. Full similarity search — finding the nearest vectors in a large table — runs in application code. The typical architecture: store embeddings in MySQL, fetch them, compute cosine similarity in your application, and return the top matches.What to Embed
The quality of your embeddings depends on what you embed. Some patterns:Frequently Asked Questions
Can I compare embeddings from different models?
No. Embeddings fromtext-embedding-3-small and gemini-embedding-001 live in different vector spaces — their similarity scores are meaningless when compared against each other. Standardize on one model per column.
How much storage do embeddings take?
A JSON array of 1536 floats is roughly 10–15 KB per row as a text string. For large tables, this adds up. Consider whether you need all embeddings stored or just the ones you’ll query against.Does ai_embedding() support batch input?
No — each call processes one text input. For bulk embedding, loop through rows in your application and callUPDATE in batches.
What happens if the text is too long?
The embedding model truncates input at its token limit (typically 8191 tokens for OpenAI models). The embedding is computed on the truncated text. For long documents, embed a summary or the first few paragraphs rather than the full text.Troubleshooting
| Problem | Solution |
|---|---|
FUNCTION ai_embedding does not exist | Run INSTALL EXTENSION vsql_ai |
ai_embedding() returns NULL | Check API key; verify model name; check max_execution_time |
| Similarity search returns wrong results | Confirm all embeddings use the same model; check that embeddings weren’t generated with different content than what you’re searching |
| Embeddings take too long to generate | Use LIMIT batches; embeddings are ~1–3 seconds each per API call |

