Użyj typu danych wektorowego ze sterownikiem JDBC

pobierz sterownik JDBC

Począwszy od wersji 13.2.0, sterownik JDBC obsługuje typ danych wektorowych . Począwszy od wersji 13.4.0, sterownik obsługuje również podtyp vector(float16). Vector jest również obsługiwany przez funkcje, takie jak parametry z wartością tabeli i narzędzie BulkCopy, z pewnymi ograniczeniami. Na tej stronie przedstawiono różne przypadki użycia typu danych wektora ze sterownikiem JDBC. Aby zapoznać się z omówieniem typów danych wektorowych , zobacz Vector data type (Typ danych wektorowych).

Tworzenie obiektu wektorowego

Klasa microsoft.sql.Vector to niestandardowa implementacja przeznaczona do reprezentowania danych wektorowych w sterowniku JDBC. Zapewnia ona ustrukturyzowany sposób obsługi danych o wysokim wymiarach, w tym serializacji i deserializacji, przy jednoczesnym zapewnieniu zgodności z typem danych wektorowych programu SQL Server. Obiekt wektorowy powinien zawierać liczbę elementów, wskaźnik typu i dane.

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

Sterownik JDBC firmy Microsoft dla programu SQL Server oferuje dwie metody inicjowania obiektu wektorowego, zapewniając elastyczność dla różnych przypadków użycia i danych wejściowych.

Tworzenie obiektu wektorowego z liczbą wymiarów i typem wektora

Konstruktor:

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

Przykład:

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

Tworzenie obiektu wektorowego z dokładnością i skalowaniem

Konstruktor:

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

Gdzie parametry są następujące:

  • precyzja: liczba wymiarów w wektorze.
  • scale: wartość skalowania, która reprezentuje liczbę bajtów na wymiar. 4 bajty reprezentuje FLOAT32.
  • data: tablica float[] zawierająca wartości liczbowe w wektorze.

Przykład:

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

Wypełnianie i pobieranie tabeli

Oto kilka przykładów kodu, które wypełniają i pobierają dane wektorowe z bazy danych. W przykładach przyjęto założenie, że tabela z kolumną wektorową zdefiniowana w następujący sposób:

CREATE TABLE sampleTable (vector_col vector(3))

Wstaw wartości za pomocą zwykłej instrukcji INSERT:

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

Wstaw wartości przy użyciu przygotowanego zapytania z parametrem wektora:

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();
}

Wstaw wartość null za pomocą przygotowanej instrukcji i parametru.

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();
}

Odczytywanie wartości wektorów z tabeli:

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 + ")");
        }
    }
}

Używanie procedur składowanych z wektorem

Z następującą procedurą składowaną:

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

Zwróć parametr wyjściowy wektora, korzystając z następującego przykładu:

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

Począwszy od wersji 13.6 przeciążenie o nazwie SQLServerCallableStatement.setObject(String, Object, int, int) i jego wariant forceEncrypt zachowują liczbę wymiarów wektora przekazaną w czwartym argumencie.

Wykorzystanie TVP z wektorem

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();
}

Począwszy od wersji 13.6, sterownik weryfikuje wynegocjowaną obsługę wektorów przed zapisaniem metadanych kolumn TVP. Wektor FLOAT16 wymaga vectorTypeSupport=v2 oraz serwera, który negocjuje wersję 2 wektorów. Sterownik odrzuca wartości TVP typu FLOAT16 w połączeniu w wersji 1 i odrzuca wszystkie natywne wartości wektorowe TVP, gdy vectorTypeSupport=off.

Używanie narzędzia SQLServerBulkCopy z tabeli źródłowej do tabeli docelowej z wektorem

Wektory mogą być używane w poleceniach kopiowania zbiorczego:

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);
    }

Używanie funkcji bulkCopy z pliku CSV do tabeli docelowej z wektorem

Wektory można importować z plików CSV.

Wklej następującą zawartość do pliku CSV o nazwie vectors.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);
}

Używanie wektorowego typu danych FLOAT16

FLOAT16 (IEEE 754 half-precision, 16-bitowe) wektory używają 2 bajtów na wymiar zamiast 4, zmniejszając tym samym o połowę wymagane miejsce do magazynowania i umożliwiają maksymalnie 3996 wymiarów na wektor (w porównaniu z 1998 dla FLOAT32) w ramach limitu 8000 bajtów TDS. Ten podtyp jest szczególnie przydatny w przypadku obciążeń sztucznej inteligencji/uczenia maszynowego na dużą skalę, takich jak wyszukiwanie podobieństwa i osadzanie magazynu, w którym ma znaczenie wydajność pamięci.

obsługa wektorów FLOAT16 jest włączona za pośrednictwem istniejącego rozszerzenia funkcji wektorowej (identyfikator FE 0x0E) z uzgadnianiem w wersji 2: klient żąda wersji 2 za pośrednictwem vectorTypeSupport właściwości połączenia, a serwer potwierdza możliwości FLOAT16 w odpowiedzi feature-ack.

Aby użyć wektorów FLOAT16, postępuj zgodnie z tymi samymi wzorcami przedstawionymi w poprzednich przykładach, zastępując element FLOAT32 wartością FLOAT16 oraz wartość skalowania 4 wartością 2. Przykład:

  • Użyj Vector.VectorDimensionType.FLOAT16 zamiast Vector.VectorDimensionType.FLOAT32.
  • Użyj skali 2 zamiast 4 podczas konstruowania wektora z dokładnością i skalą.
  • Zdefiniuj kolumny SQL jako vector(3, float16) zamiast vector(3).

Oto przykład tworzenia obiektu wektora 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});

Konwertuj wektory między formatami FLOAT16 i FLOAT32

Na serwerach obsługujących konwersję wektorów między typami program SQL Server może niejawnie lub jawnie konwertować między wektorami FLOAT16 i FLOAT32. Przykład:

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;

Wektory źródłowe i docelowe muszą mieć tę samą liczbę wymiarów. Konwersja z FLOAT32 do FLOAT16 może prowadzić do utraty precyzji, ponieważ FLOAT16 ma mniejszy zakres reprezentowanych wartości i mniej bitów znaczących. Wartości zerowe pozostają zerowe po konwersji. Te konwersje mają również zastosowanie do przypisań za pomocą instrukcji przygotowanych, parametrów procedur składowanych, parametrów o wartościach tabelarycznych oraz kopiowania zbiorczego.

Zgodność z poprzednimi wersjami

Jeśli aplikacja nie jest aktualizowana w celu obsługi typu danych wektorowych , sterownik zapewnia zgodność z poprzednimi wersjami, umożliwiając odczyt typów danych wektorowych jako typy zgodne z poprzednimi wersjami. To zachowanie jest kontrolowane za pomocą vectorTypeSupport właściwości parametrów połączenia. Obsługiwane wartości to off (serwer wysyła typy wektorów jako dane ciągu w formacie JSON), v1 (serwer wysyła typy wektorów FLOAT32 jako dane wektorowe) i v2 (aby włączyć obsługę typów wektorów dla FLOAT16). Domyślna wartość to v1.

Ograniczenia wektora

Aby uzyskać szczegółowe ograniczenia, zobacz Ograniczenia typów danych wektorów.