將向量資料類型與 JDBC 驅動程式搭配使用

下載 JDBC 驅動程式

從 13.2.0 版開始,JDBC 驅動程式支援 向量 資料類型。 從 13.4.0 版本開始,驅動程式也支援 向量(float16)子 型。 Vector 也支援 Table-Valued Parameters 和 BulkCopy 等功能,但有一些限制。 此頁面顯示 JDBC 驅動程式之 向量 資料類型的各種使用案例。 如需 向量 資料類型的概觀,請參閱 向量資料類型。

建立向量物件

microsoft.sql.Vector 類別是一種自訂實作,旨在表示 JDBC 驅動程式中的向量資料。 它提供了一種結構化方法來處理高維數據,包括序列化和還原序列化,同時確保與 SQL Server 向 量 資料類型的兼容性。 向量物件應包含元素數、類型指示器和資料。

public enum VectorDimensionType {
        FLOAT32 // 32-bit (single precision) float
}

private VectorDimensionType vectorType; // The type of values in the data array
private int dimensionCount; // Number of dimensions in the vector
private Object[] data; // An array containing the vector's numerical values

適用於 SQL Server 的 Microsoft JDBC 驅動程式提供兩種初始化向量物件的方法,為不同的用例和輸入資料提供靈活性。

建立具有維度計數和向量類型的向量物件

建構函式:

public Vector(int dimensionCount, VectorDimensionType vectorType, Object[] data);

範例:

Vector vector = new Vector(3, Vector.VectorDimensionType.FLOAT32, new Float[]{1.0f, 2.0f, 3.0f});

建立具有精確度和比例的向量物件

建構函式:

public Vector(int precision, int scale, Object[] data);

參數如下:

  • precision: 向量中的維度數。
  • scale:比例值,代表每個維度的位元組數。 4 個位元組代表一個FLOAT32。
  • data:包含 向量中數值的float[]陣列。

範例:

Vector vector = new Vector(3, 4, new Float[]{1.0f, 2.0f, 3.0f});

填充和檢索資料表

以下是一些從資料庫填入和擷取 向量 資料的程式碼範例。 這些範例假設表格具有 向量 欄,定義如下:

CREATE TABLE sampleTable (vector_col vector(3))

使用一般的 INSERT 陳述式插入值:

try (Statement stmt = connection.createStatement()){
    stmt.execute("insert into sampleTable values ('[0.1, 2.0, 3.0]')");
}

插入具有預備陳述式和 向量 參數的值:

Vector vector = new Vector(3, Vector.VectorDimensionType.FLOAT32, new Float[]{1.0f, 2.0f, 3.0f});
try (PreparedStatement preparedStatement = con.prepareStatement("insert into sampleTable values (?)")) {
    preparedStatement.setObject(1, vector, microsoft.sql.Types.VECTOR);
    preparedStatement.execute();
}

使用準備好的語句和參數插入空值:

Vector vector = new Vector(1, Vector.VectorDimensionType.FLOAT32, null);
try (PreparedStatement preparedStatement = con.prepareStatement("insert into sampleTable values (?)")) {
    preparedStatement.setObject(1, vector, microsoft.sql.Types.VECTOR);
    preparedStatement.execute();
}
try (PreparedStatement preparedStatement = con.prepareStatement("insert into sampleTable values (?)")) {
    preparedStatement.setObject(1, null)
    preparedStatement.execute();
}

從表格中讀取 向量 值:

try (SQLServerResultSet resultSet = (SQLServerResultSet) stmt.executeQuery("select * from sampleTable")) {
    assertTrue(resultSet.next(), "No result found for inserted vector.");
    ResultSetMetaData metaData = resultSet.getMetaData();
    int columnCount = metaData.getColumnCount();

    while (resultSet.next()) {
        for (int i = 1; i <= columnCount; i++) {
            String columnName = metaData.getColumnName(i);
            int columnType = metaData.getColumnType(i); // from java.sql.Types

            Object value = null;
            switch (columnType) {
                case Types.VARCHAR:
                case Types.NVARCHAR:
                    value = resultSet.getString(i);
                    break;
                case microsoft.sql.Types.VECTOR:
                    value = resultSet.getObject(i, microsoft.sql.Vector.class);
            }

            System.out.println(columnName + " = " + value + " (type: " + columnType + ")");
        }
    }
}

將預存程序與向量搭配使用

使用下列預存程序:

String sql = "CREATE PROCEDURE " + inputProc +
             " @p0 VECTOR(3) OUTPUT AS " +
             " SELECT TOP 1 @p0 = col_vector FROM sampleTable ";

使用下列範例傳回 向量 輸出參數:

try (CallableStatement callableStatement = con.prepareCall("{call " + inputProc + " (?) }")) {
    callableStatement.registerOutParameter(1, microsoft.sql.Types.VECTOR, 3, 4);
    callableStatement.execute();
}

從 13.6 版開始,名為 SQLServerCallableStatement.setObject(String, Object, int, int) 的多載版本及其 forceEncrypt 變體版本會保留由第四個引數指定的向量維度數。

使用 TVP 與向量

Vector vector = new Vector(3, Vector.VectorDimensionType.FLOAT32, new Float[]{1.0f, 2.0f, 3.0f});
SQLServerDataTable tvp = new SQLServerDataTable();
tvp.addColumnMetadata("vector_col", microsoft.sql.Types.VECTOR);
tvp.addRow(vector);

try (SQLServerPreparedStatement preparedStatement = (SQLServerPreparedStatement) con.prepareStatement( "insert into sampleTable select * from (?)")) {
    pstmt.setStructured(1, TVP_NAME, tvp);
    pstmt.execute();
}

從版本 13.6 開始,驅動程式在寫入 TVP 欄位元資料前,先驗證協商向量支援。 FLOAT16向量需要 vectorTypeSupport=v2 ,且伺服器能協商向量版本2。 驅動程式會在第 1 版連線上拒絕 FLOAT16 TVP 值,並在 vectorTypeSupport=off 時拒絕所有原生向量 TVP 值。

使用 SQLServerBulkCopy 從來源資料表複製到目的地資料表

向量可用於大量複製命令:

Vector vector = new Vector(3, Vector.VectorDimensionType.FLOAT32, new Float[]{1.0f, 2.0f, 3.0f});
try (Statement stmt = con.createStatement();
        SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(con)) {

        stmt.executeUpdate("create table destinationTable (vector_col vector(3))");

        bulkCopy.setDestinationTableName("destinationTable");
        bulkCopy.writeToServer(vector);
    }

使用 bulkCopy 從 csv 檔案以向量格式複製到目標表格

向量可以從 CSV 檔案匯入。

將下列內容貼到名為 vectors.csv的 CSV 檔案中:

vector_col
"[1.0,2.0,3.0]"
"[4.0,5.0,6.0]"
try (Statement stmt = con.createStatement();
    SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(con);
    SQLServerBulkCSVFileRecord fileRecord = new SQLServerBulkCSVFileRecord("vectors.csv", null, ",", true)) {

        stmt.executeUpdate("create table destinationTable (vector_col vector(3))");

        // Add column metadata for the CSV file
        fileRecord.addColumnMetadata(1, "vector_col", microsoft.sql.Types.VECTOR, 3, 4);
        fileRecord.setEscapeColumnDelimitersCSV(true);

        bulkCopy.setDestinationTableName("destinationTable");
        bulkCopy.writeToServer(fileRecord);
}

使用向量FLOAT16資料型別

FLOAT16(IEEE 754 半精度、16 位元)向量每維度使用 2 位元組,而非 4 個位元組,將儲存空間減半,並在 8,000 位元組 TDS 限制內,每個向量最多可達 3,996 維(較FLOAT32 的 1,998 維度為高)。 此子類型對於大型 AI/ML 工作負載(如相似度搜尋與嵌入儲存)特別有價值,因為記憶體效率很重要。

FLOAT16 向量支援是透過現有的向量功能擴充(FE 識別碼 0x0E),並以版本 2 握手的方式啟用:客戶端透過 vectorTypeSupport 連線屬性請求 v2,伺服器則在功能確認響應中確認 FLOAT16 功能。

使用FLOAT16向量时,按照前述範例所示模式,把FLOAT32替換為FLOAT16,將尺度值4替換成2。 例如:

  • 使用 Vector.VectorDimensionType.FLOAT16,而不是 Vector.VectorDimensionType.FLOAT32。
  • 在構造具有精確度和規模的向量時,請使用比例 2 代替 4。
  • 將 SQL 欄位定義為 vector(3, float16) ,而非 vector(3)。

這裡有一個建立FLOAT16向量物件的範例:

// Using dimension count and vector type
Vector vector = new Vector(3, Vector.VectorDimensionType.FLOAT16, new Float[]{1.0f, 2.0f, 3.0f});

// Using precision and scale (2 bytes = FLOAT16)
Vector vector = new Vector(3, 2, new Float[]{1.0f, 2.0f, 3.0f});

在FLOAT16向量與FLOAT32向量間轉換

在支援跨型向量轉換的伺服器上,SQL Server可以隱含或顯式地在FLOAT16向量與FLOAT32向量間轉換。 例如:

INSERT INTO float32Table (vector_col)
SELECT vector_col FROM float16Table;

SELECT CAST(vector_col AS VECTOR(3, float32))
FROM float16Table;

SELECT CONVERT(VECTOR(3, float16), vector_col)
FROM float32Table;

來源向量與目的向量的維度數必須相同。 從 FLOAT32 轉換成 FLOAT16 可能會因為FLOAT16可表示範圍較小且有效位元較少而失去精度。 Null 值在轉換後仍為 null。 這些轉換同樣適用於透過預備語句、儲存程序參數、表值參數及批量複製的指派。

回溯相容性

如果應用程式未更新以處理 向量 資料類型,驅動程式會允許 將向量 資料類型讀取為回溯相容類型,以提供回溯相容性。 此行為由 vectorTypeSupport 連接字串屬性控制。 支援的值包括 off (伺服器以 JSON 格式的字串資料傳送 向量 類型)、 v1 (伺服器以向量資料形式傳送FLOAT32 向量 類型)、以及 v2 (以啟用 向量 類型支援FLOAT16)。 預設值是 v1。

向量的局限性

如需詳細限制,請參閱 向量資料類型限制。