Known limitations¶
What MyVector does not do today, or does differently than you might expect. Each item links to the issue tracking it. Items marked (untested) are not verified by this project's tests.
Search¶
MYVECTOR_IS_ANN(...)on component builds needs a build that includes #156. The annotation is a query rewrite. Component builds (INSTALL COMPONENT) from v1.26.9 and earlier releases don't have it (#144); on those, callmyvector_ann_set()directly. Components built frommainafter #156 have the rewrite, verified on MySQL 8.4.8, 8.4.11, 9.7.0 and 26.7.0 with components built by the repo's build scripts on aarch64. #174 reports the rewrite not firing on 8.4.11 in one setup, which we could not reproduce. IfMYVECTOR(...)orMYVECTOR_IS_ANNfails on your server, use theMYVECTOR COLUMNcomment andmyvector_ann_set(), which work on every build. Plugin builds have always had the rewrite.- Uninstalling a component that has the query rewrite can fail with ERROR 3540 while
another session that has run a query since the install is still connected. The binlog
listener of an
online=Yindex is such a session. Disconnect the other sessions (for the binlog listener, drop theonline=Yindexes) and retry (#155). - Filtered search takes an explicit key list. Pass the allowed keys as the fifth
argument, e.g.
MYVECTOR_IS_ANN(..., 10, (SELECT JSON_ARRAYAGG(id) FROM t WHERE ...))(see Usage). A predicate written next toMYVECTOR_IS_ANN(...)in the sameWHEREclause is still applied to the k results afterwards, so it can return fewer than k rows. Building the key list costs one scan of the matching rows, which is slow when the filter matches most of a large table. For those filters, useCALL mysql.MYVECTOR_ANN_FILTERED(...)(see Usage). MYVECTOR_ANN_FILTEREDreturns a result set. You cannot join it or use it inside another query. When the predicate is so selective that 10,000 candidates hold fewer than k matches, it builds the key list after all: it then does the key list's work plus the rounds of candidates before it. It uses the session variables@_myvector_sql,@_myvector_jsand@_myvector_n, and sets them to NULL when it is done. It also uses the prepared statement name_myvector_stmt, which replaces a statement of the same name in the session. A row written between its last round and its final query can make it return fewer than k rows.- Approximate results. HNSW is approximate: recall depends on
ef/ef_search. The benchmark's recall@10 (0.978 on plugin 8.4) was measured on synthetic vectors at a single setting and is not comparable with published results (#131).
Building and running an index¶
- The index build connects back to the server.
MYVECTOR_INDEX_BUILDneedsmyvector.cnf(host, user, password, port). Without it the procedure returns an error row such asCan't connect to local MySQL server through socket '', and no index is built. Check the returned text: it is not an SQL error. - Index files live in
myvector_index_dir. The plugin has this as a system variable (default/mysqldata, which must exist and be writable). The component has no such variable: index files are written relative to the server's data directory. - A failed save is reported, not fatal. Since v1.26.9-rc2 a build or
savethat cannot write the index returnsERROR: ...and leaves the server running. On v1.26.9-rc1 the same failure abortedmysqld.
Index options and DDL¶
- Options are matched exactly, and unknown values fall back silently (#119).
dist=cosine(lower case) becomes L2; useCosine,CosineNormorAngular. Integer keys are case-sensitive too, som=64is ignored and the default is used; writeM=64.MYVECTOR_INDEX_STATUSprints the option as written, not the effective setting. typeis case-insensitive since v1.26.9-rc2 (hnswandHNSWboth build HNSW). A column comment written without the|marker (MYVECTOR COLUMN type=hnsw,...) now builds HNSW; on earlier versions it silently built a brute-force KNN index.- A misspelled or missing
typeis an error.MYVECTOR_INDEX_BUILDreturnsERROR: unknown index type 'hnws' ...orERROR: missing index type ...and builds nothing. Earlier versions built a brute-force KNN index and returnedSUCCESS. A column comment with notype=must now saytype=KNNexplicitly. The plugin'sMYVECTOR(...)DDL still defaults a missing type to KNN, and now rejects an unknown one atCREATE TABLE. - A line break or tab after
MYVECTOR COLUMN(a multi-lineCOMMENT) is read like a space (#158). Before this fix such a comment silently built a KNN index; if you built one on an earlier version, checkType :inMYVECTOR_INDEX_STATUS. The comment must still start withMYVECTOR COLUMN: the index procedures reject leading whitespace with "not a MYVECTOR column". - The
MYVECTOR(...)column type is matched literally. The plugin's DDL rewrite looks for the upper-case textMYVECTOR(with no space.myvector (type=...)is a syntax error. ACOMMENT 'MYVECTOR(...)'string has also been seen to fail on the plugin image (#130, observed once, not yet investigated). On MySQL 9.x use the nativeVECTOR(n)type with aCOMMENT, as in Docker images.
Data model¶
- Row keys are
INT/BIGINTonly (KeyTypeInteger). - Vectors are 32-bit floats (
FP32); the default maximum dimension is 4096 (myvector_max_vector_dim, a plugin variable). - Distance metrics: L2, Cosine and inner product.
Platforms and versions¶
Plugin (INSTALL PLUGIN) |
Component (INSTALL COMPONENT) |
|
|---|---|---|
| MySQL 8.0 | yes | no build planned |
| MySQL 8.4 | yes | yes |
| MySQL 9.x | 9.0 and 9.7 | 9.7 |
| MySQL 26.7 (Innovation) | no (ABI) | yes; new, short track record |
- Windows is not supported (#80).
- MariaDB and Percona Server are not built or tested.
- macOS: no prebuilt binaries; use the Docker images, or see Building on macOS. There is no Homebrew formula.
Benchmarks¶
- Query QPS and latency are dominated by
docker execoverhead (about 67 ms per query), so they are weak regression signals (#124). Recall, index build time and batched insert throughput are meaningful. - The benchmark uses synthetic data and one
ef_searchsetting (#131), and runs against a containerised server, not a bare-metal one (#133).