sentence_transformers
.
Enabling PlanetScale vectors
PlanetScale has a custom version of MySQL that has been extended with vector support. Vector support can be enabled on a per-branch basis. The branch will be updated to the vectors-capable version of MySQL. Branches with vectors enabled will repurpose half of the memory in the InnoDB buffer pool for use with vectors. To enable the vector support on a branch:1
In the database where you want to use vectors, navigate to the โBranchesโ tab, and click on the branch where you would like to enable vector support.
2
Click on the small gear icon underneath the โConnectโ button on the right.
3
Click the toggle next to โEnable vectorsโ.
4
Click โSave branch settingsโ.
5
The branch will upgrade asynchronously to the correct version of MySQL, which may take 30-60 minutes. While this happens, the database dashboard will show an โEnabling vectorsโ badge, which changes to a โVector-enabledโ badge when the upgrade is complete.
Adding vector columns
As a first step, create one or more columns with the VECTOR type and then insert some vectors. Hereโs an example:QUERY_TIMEOUT_MS
comment is optional, but important for tables over 100,000 rows. Vector indexes take a significant amount of time to build, and the comment allows the CREATE
statement to bypass Vitessโs usual timeout.
Then, you can perform similarity searches like so:
EXPLAIN
query to confirm that the query uses the new index. This query actually wonโt use the index until the table has around 50 rows in it.
Vector indexes provide approximate results. An unindexed query with LIMIT 100 returns exactly the 100 rows closest to the reference vector, after performing a full table scan and a sort. An indexed query returns, on average, about 100 of the top 105 (around 95%) of the rows closest to the reference vector, but much faster than a full table scan. This is expected, because all efficient vector indexes, including PlanetScaleโs vector indexes, perform approximate nearest neighbor (ANN) searches.
If you are adding vectors to your database from an application, you may want to use prepared statements, although we do not recommend it. TO_VECTOR
works in that setting, but serializing the vectors on the client side and uploading them as binary is faster. The serialized format is IEEE-754 32-bit floats, which you can serialize with code like this:
- Python:
struct.pack(f'{len(float_array)}f', *float_array)
- Ruby:
float_array.pack(โf*โ)
- Rust:
float_array.map(|f| f.to_ne_bytes()).flatten().collect()
INSERT
statement like this:
Vector index parameters
Statements that create a vector index take optional parameters, which can be specified as JSON key-value pairs, like so:type
attribute specifies the algorithm used to build and query the vector index. It is optional, and the only valid value is spann
, which is the default. The distance
attribute specifies the distance metric that queries will use, and can be any of the following:
dot
for the dot productcosine
for the cosine of the angle between the two vectors.l2
oreuclidean
for the length of a line between the ends of the vectorsl2_squared
oreuclidean_squared
for the square of the Euclidean distance. This is the default.
distance
metric specified at index creation time must match the distance metric used at query time, or the index cannot be used, and MySQL will perform a full-table scan instead.
Other possible options include fixed_quantization
and product_quantization
, which configure vector compression in the index, resulting in lower storage requirements and faster query times. See the Quantization section for more information.
Filtered vector queries
Vector data is stored in tables alongside any other relational data, and sometimes applications need to query, join, or filter based on that relational data. In particular, queries withWHERE
clauses work, and MySQL chooses the index or indexes that allow the query to complete the fastest. For example, in a table of products for sale containing indexed columns for price and seller ID, here are how two queries might be executed:
EXPLAIN
on any given query to see how it will execute.
As we continue to refine vectors support, weโre looking for feedback on how well MySQL plans vector queries. If you believe youโve hit an edge case or something looks wrong, please open a support ticket and let us know.
Resource requirements
A vector index with default parameters requires 3-4x as much disk space as the underlying data in the vector column, and it requires around 15% as much memory as the underlying data. For example, a vector column with 1536 dimensions and a million rows takes up 1536 * 1000000 * 4 = 5.7GiB of space in the table. The corresponding index will be 18-24GiB, and it will require around 800MiB of memory to build and query. Using quantization settings other than the default will increase or decrease the required disk space and memory proportional to how much less or more each vector gets compressed relative to the 16-bit default. PlanetScale scales storage space automatically for any branch backed by EBS. On Metal, make sure the instance size you choose has enough storage for the vector indexes you plan to create. By default, vector indexes reserve half of the buffer-pool memory allocated to each instance, equal to about one third of overall instance memory. This tradeoff can be changed in the cluster configuration for any branch with vectors enabled.Usage recommendations
- Incremental indexes (indexes that begin empty and update as new vectors are added) function correctly, but are significantly slower to build compared to a one-shot index (an index built on an existing set of vectors). Disk usage is much higher due to potentially very high InnoDB blob fragmentation issues, so itโs much easier to run out of disk space.
- Once you opt a branch into the vectors feature, that branch must continue to run a vectors-enabled version of MySQL. You can remove your vector columns/tables, but you cannot downgrade that branch to its prior version of MySQL.