🍎

[MySQL]MySQL9.0 でベクトル型のカラムや関連する組み込み関数がリリースされているので触ってみる

2024/07/27に公開

TL;DR

  • MySQL9.0 から VECTOR 型というベクトル化されたデータを扱うためのカラムが定義できる
  • 2024年7月27日現在では下記の組み込み関数が用意されている
    • ベクトル化されたデータの文字列からバイナリへの変換:STRING_TO_VECTOR()
    • ベクトル化されたデータの長さの取得:VECTOR_DIM()
    • バイナリからベクトル化されたデータの文字列への変換:VECTOR_TO_STRING()
  • 詳細は以下の公式のドキュメントを参照

予備知識の整理(ベクトル化)

(当方、機械学習エンジニアではなくこの辺の知識には疎いのであらためて整理)
機械学習や自然言語を扱う上でのベクトル化とは何か。neptune.ai の blog によると下記のように解説されている。

Vectorization Techniques in NLP [Guide] - What is vectorization?

What is vectorization?

  • Vectorization is jargon for a classic approach of converting input data from its raw format (i.e. text ) into vectors of real numbers which is the format that ML models support. This approach has been there ever since computers were first built, it has worked wonderfully across various domains, and it’s now used in NLP.
  • In Machine Learning, vectorization is a step in feature extraction. The idea is to get some distinct features out of the text for the model to train on, by converting text to numerical vectors.

ベクトル化とは何ですか?

  • ベクトル化とは、入力データを生の形式 (つまりテキスト) から ML モデルがサポートする形式である実数のベクトルに変換する古典的なアプローチの専門用語です。このアプローチは、コンピューターが最初に構築されて以来存在しており、さまざまな分野で素晴らしい成果を上げており、現在は NLP でも使用されています。
  • 機械学習では、ベクトル化は特徴抽出のステップです。テキストを数値ベクトルに変換することで、テキストからいくつかの明確な特徴を取得し、モデルをトレーニングするという考え方です。

上記ブログや一般論などを踏まえ、当方は雑にざっくり下記のように解釈している。

  • 機械学習におけるベクトルはデータの類似性に基づく検索などにおいて重要
  • 特徴を抽出するための手法としてベクトル化を使う
  • 類似性を比較するために特徴を数値化・リスト化してベクトル表現のデータを生成する

雑に触ってみた

Docker の公式イメージから 9.0 のタグを使用。

適当なデータベースの作成。

mysql> CREATE DATABASE IF NOT EXISTS `vectordb`;
Query OK, 1 row affected (0.01 sec)

mysql> USE `vectordb`;
Database changed

VECTOR 型データを扱うためのテーブルの作成。

mysql> CREATE TABLE IF NOT EXISTS v1 (c1 VECTOR(5000));
Query OK, 0 rows affected (0.02 sec)

ベクトル化のための組み込み関数はまだ存在しないため、 ChatGPT(4o) によりベクトル化されたダミーデータを用意。動物の名前10匹を求めるようなプロンプトで生成(合っているのかは知らん)。

[0.5488135, 0.71518937, 0.60276338, 0.54488318, 0.4236548, 0.64589411, 0.43758721, 0.891773, 0.96366276, 0.38344152]
[0.79172504, 0.52889492, 0.56804456, 0.92559664, 0.07103606, 0.0871293, 0.0202184, 0.83261985, 0.77815675, 0.87001215]
[0.97861834, 0.79915856, 0.46147936, 0.78052918, 0.11827443, 0.63992102, 0.14335329, 0.94466892, 0.52184832, 0.41466194]
[0.26455561, 0.77423369, 0.45615033, 0.56843395, 0.0187898, 0.6176355, 0.61209572, 0.616934, 0.94374808, 0.6818203]
[0.3595079, 0.43703195, 0.6976312, 0.06022547, 0.66676672, 0.67063787, 0.21038256, 0.1289263, 0.31542835, 0.36371077]
[0.57019677, 0.43860151, 0.98837384, 0.10204481, 0.20887676, 0.16130952, 0.65310833, 0.2532916, 0.46631077, 0.24442559]
[0.15896958, 0.11037514, 0.65632959, 0.13818295, 0.19658236, 0.36872517, 0.82099323, 0.09710128, 0.83794491, 0.09609841]
[0.97645947, 0.4686512, 0.97676109, 0.60484552, 0.73926358, 0.03918779, 0.28280696, 0.12019656, 0.2961402, 0.11872772]
[0.31798318, 0.41426299, 0.0641475, 0.69247212, 0.56660145, 0.26538949, 0.52324805, 0.09394051, 0.5759465, 0.9292962]
[0.31856895, 0.66741038, 0.13179786, 0.7163272, 0.28940609, 0.18319136, 0.58651293, 0.02010755, 0.82894003, 0.00469548]

データ投入。STRING_TO_VECTOR() というベクトル化されたデータの文字列からバイナリへの変換を行う組み込み関数を使っている。

mysql> INSERT INTO v1 (c1) VALUES
    -> (STRING_TO_VECTOR("[0.5488135, 0.71518937, 0.60276338, 0.54488318, 0.4236548, 0.64589411, 0.43758721, 0.891773, 0.96366276, 0.38344152]")),
    -> (STRING_TO_VECTOR("[0.79172504, 0.52889492, 0.56804456, 0.92559664, 0.07103606, 0.0871293, 0.0202184, 0.83261985, 0.77815675, 0.87001215]")),
    -> (STRING_TO_VECTOR("[0.97861834, 0.79915856, 0.46147936, 0.78052918, 0.11827443, 0.63992102, 0.14335329, 0.94466892, 0.52184832, 0.41466194]")),
    -> (STRING_TO_VECTOR("[0.26455561, 0.77423369, 0.45615033, 0.56843395, 0.0187898, 0.6176355, 0.61209572, 0.616934, 0.94374808, 0.6818203]")),
    -> (STRING_TO_VECTOR("[0.3595079, 0.43703195, 0.6976312, 0.06022547, 0.66676672, 0.67063787, 0.21038256, 0.1289263, 0.31542835, 0.36371077]")),
    -> (STRING_TO_VECTOR("[0.57019677, 0.43860151, 0.98837384, 0.10204481, 0.20887676, 0.16130952, 0.65310833, 0.2532916, 0.46631077, 0.24442559]")),
    -> (STRING_TO_VECTOR("[0.15896958, 0.11037514, 0.65632959, 0.13818295, 0.19658236, 0.36872517, 0.82099323, 0.09710128, 0.83794491, 0.09609841]")),
    -> (STRING_TO_VECTOR("[0.97645947, 0.4686512, 0.97676109, 0.60484552, 0.73926358, 0.03918779, 0.28280696, 0.12019656, 0.2961402, 0.11872772]")),
    -> (STRING_TO_VECTOR("[0.31798318, 0.41426299, 0.0641475, 0.69247212, 0.56660145, 0.26538949, 0.52324805, 0.09394051, 0.5759465, 0.9292962]")),
    -> (STRING_TO_VECTOR("[0.31856895, 0.66741038, 0.13179786, 0.7163272, 0.28940609, 0.18319136, 0.58651293, 0.02010755, 0.82894003, 0.00469548]"));
Query OK, 10 rows affected (0.01 sec)
Records: 10  Duplicates: 0  Warnings: 0

公式では扱えるデータについて、下記のように「バイナリ文字列またはリスト形式の文字列」とある。

1.4 What Is New in MySQL 9.0

A vector is a data structure which consists of a list of entries (4-byte floating-point values) which can be expressed either as a binary string value or a list-formatted string.

ベクトルは、バイナリ文字列値またはリスト形式の文字列として表現できるエントリのリスト (4 バイトの浮動小数点値) で構成されるデータ構造です。

しかし、STRING_TO_VECTOR() を通さずにデータを投入しようとすると convert できない旨のエラーが発生した。保持するデータはバイナリである必要がありそう。

mysql> INSERT INTO v1 (c1) VALUES
    -> ('[0.5488135, 0.71518937, 0.60276338, 0.54488318, 0.4236548, 0.64589411, 0.43758721, 0.891773, 0.96366276, 0.38344152]'),
    -> ('[0.79172504, 0.52889492, 0.56804456, 0.92559664, 0.07103606, 0.0871293, 0.0202184, 0.83261985, 0.77815675, 0.87001215]'),
    -> ('[0.97861834, 0.79915856, 0.46147936, 0.78052918, 0.11827443, 0.63992102, 0.14335329, 0.94466892, 0.52184832, 0.41466194]'),
    -> ('[0.26455561, 0.77423369, 0.45615033, 0.56843395, 0.0187898, 0.6176355, 0.61209572, 0.616934, 0.94374808, 0.6818203]'),
    -> ('[0.3595079, 0.43703195, 0.6976312, 0.06022547, 0.66676672, 0.67063787, 0.21038256, 0.1289263, 0.31542835, 0.36371077]'),
    -> ('[0.57019677, 0.43860151, 0.98837384, 0.10204481, 0.20887676, 0.16130952, 0.65310833, 0.2532916, 0.46631077, 0.24442559]'),
    -> ('[0.15896958, 0.11037514, 0.65632959, 0.13818295, 0.19658236, 0.36872517, 0.82099323, 0.09710128, 0.83794491, 0.09609841]'),
    -> ('[0.97645947, 0.4686512, 0.97676109, 0.60484552, 0.73926358, 0.03918779, 0.28280696, 0.12019656, 0.2961402, 0.11872772]'),
    -> ('[0.31798318, 0.41426299, 0.0641475, 0.69247212, 0.56660145, 0.26538949, 0.52324805, 0.09394051, 0.5759465, 0.9292962]'),
    -> ('[0.31856895, 0.66741038, 0.13179786, 0.7163272, 0.28940609, 0.18319136, 0.58651293, 0.02010755, 0.82894003, 0.00469548]');
ERROR 6136 (HY000): Value of type 'string, size: 116' cannot be converted to 'vector' type.

投入したデータを見てみる。16進数のバイナリになっている。

mysql> SELECT * FROM v1;
+------------------------------------------------------------------------------------+
| c1                                                                                 |
+------------------------------------------------------------------------------------+
| 0x0B7F0C3FA716373FB34E1A3F777D0B3F48E9D83E5159253F6E0BE03E3C4B643F9AB2763F7252C43E |
| 0x7EAE4A3FA865073F5E6B113FE7F36C3F5B7B913DD970B23D0FA1A53C9326553F4835473F1EB95E3F |
| 0xBB867A3FA8954C3F0647EC3EC3D0473FDD39F23DDDD1233F34CB123ED3D5713FDA97053F924ED43E |
| 0xD573873E2E34463F898CE93EE384113F11ED993C5C1D1E3F4EB21C3F63EF1D3F7999713FC68B2E3F |
| 0x6B11B83EA7C2DF3EF597323FFCAE763D39B12A3FECAE2B3F876E573E4205043ED37FA13E4C38BA3E |
| 0x6AF8113F6190E03E11067D3FDFFCD03DCAE3553E532E253E1C32273F70AF813E49C0EE3EB44A7A3E |
| 0xECC8223E5D0CE23D3705283FD57F0D3EE34C493E8CC9BC3E9D2C523F09DDC63D8F83563F3ECFC43D |
| 0x3FF9793F0DF3EF3E040D7A3F28D71A3F61403D3F6083203D13CC903E9D29F63DB09F973E8527F33D |
| 0xB1CEA23E471AD43EC45F833DDA45313FCB0C113F22E1873E96F3053FE263C03D3B71133F5BE66D3F |
| 0x781BA33E68DB2A3F05F6063E3861373F092D943E84963B3EB625163F97B8A43C6A35543F8BDC993B |
+------------------------------------------------------------------------------------+
10 rows in set (0.00 sec)

バイナリからベクトル化されたデータの文字列に戻してみる。VECTOR_TO_STRING() の組み込み関数を使う。指数表記になっているが元のデータへ変換されていそう。

mysql> SELECT VECTOR_TO_STRING(0x0B7F0C3FA716373FB34E1A3F777D0B3F48E9D83E5159253F6E0BE03E3C4B643F9AB2763F7252C43E);
+---------------------------------------------------------------------------------------------------------------------------+
| VECTOR_TO_STRING(0x0B7F0C3FA716373FB34E1A3F777D0B3F48E9D83E5159253F6E0BE03E3C4B643F9AB2763F7252C43E)                      |
+---------------------------------------------------------------------------------------------------------------------------+
| [5.48814e-01,7.15189e-01,6.02763e-01,5.44883e-01,4.23655e-01,6.45894e-01,4.37587e-01,8.91773e-01,9.63663e-01,3.83442e-01] |
+---------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

ベクトル化されたデータの長さを取得してみる。VECTOR_DIM() の組み込み関数を使う。
前述の VECTOR_TO_STRING() の結果(元のリスト形式のデータ)と比べても要素数が一致していることが確認できる。

mysql> SELECT VECTOR_DIM(0x0B7F0C3FA716373FB34E1A3F777D0B3F48E9D83E5159253F6E0BE03E3C4B643F9AB2763F7252C43E);
+------------------------------------------------------------------------------------------------+
| VECTOR_DIM(0x0B7F0C3FA716373FB34E1A3F777D0B3F48E9D83E5159253F6E0BE03E3C4B643F9AB2763F7252C43E) |
+------------------------------------------------------------------------------------------------+
|                                                                                             10 |
+------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

ここまで解説した本機能は MySQL 公式ドキュメントの下記に記載されている。

感想

時代というかトレンドを感じた。今後自然言語からベクトル表現のデータを生成したり、類似度を測ったりできるような組み込み関数のアップデートがあると使い道がさらに広がりそう。わくわく。

Discussion