Compartilhar via


Usar o tipo de dados vetoriais com o driver JDBC

Baixar JDBC Driver

A partir da versão 13.2.0, o driver JDBC dá suporte ao tipo de dados de vetor . A partir da versão 13.4.0, o driver também dá suporte ao subtipo de vetor(float16 ). O Vector também é compatível com recursos como Parâmetros do tipo tabela e BulkCopy, com algumas limitações. Esta página mostra diversos casos de uso do tipo de dados vetor com o JDBC Driver. Para obter uma visão geral dos tipos de dados de vetor , consulte o tipo de dados vetor.

Criar um objeto de vetor

A classe microsoft.sql.Vector é uma implementação personalizada projetada para representar dados de vetor no driver JDBC. Ele fornece uma maneira estruturada de lidar com dados de alta dimensão, incluindo serialização e desserialização, garantindo a compatibilidade com o tipo de dados de vetor do SQL Server. O objeto vetor deve incluir o número de elementos, o indicador de tipo e os dados.

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

O Microsoft JDBC Driver for SQL Server oferece dois métodos para inicializar um objeto vetor, fornecendo flexibilidade para diferentes casos de uso e dados de entrada.

Criar um objeto de vetor com contagem de dimensões e tipo de vetor

Construtor:

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

Exemplo:

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

Criar um objeto de vetor com precisão e escala

Construtor:

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

Onde estão os parâmetros:

  • precisão: o número de dimensões no vetor.
  • escala: o valor de escala, que representa o número de bytes por dimensão. 4 bytes representam um FLOAT32.
  • data: uma matriz float[] que contém os valores numéricos no vetor.

Exemplo:

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

Preencher dados e recuperar uma tabela

Aqui estão alguns exemplos de código que preenchem e recuperam dados de vetor de um banco de dados. Os exemplos pressupõem uma tabela com uma coluna de vetor , definida da seguinte maneira:

CREATE TABLE sampleTable (vector_col vector(3))

Inserir valores com uma instrução INSERT simples:

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

Insira valores com uma instrução preparada e um parâmetro de vetor :

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

Insira um valor nulo com uma instrução preparada e um parâmetro:

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

Ler valores de vetor de uma tabela:

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

Usar procedimentos armazenados com vetor

Com o seguinte procedimento armazenado:

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

Retorne um parâmetro de saída vetor com o seguinte exemplo:

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

Usar TVP com vetor

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

Usar SQLServerBulkCopy da tabela de origem para a tabela de destino com vetor

Os vetores podem ser usados em comandos de cópia em massa:

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

Usar bulkCopy do arquivo csv para a tabela de destino com vetor

Os vetores podem ser importados de arquivos CSV.

Cole o seguinte conteúdo em um arquivo CSV chamado 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);
}

Usar o tipo de dado vetor FLOAT16

FLOAT16 (IEEE 754 de meia precisão, 16 bits), os vetores usam 2 bytes por dimensão em vez de 4, reduzindo pela metade o volume de armazenamento e permitindo até 3.996 dimensões por vetor (vs. 1.998 para FLOAT32) dentro do limite de TDS de 8.000 bytes. Esse subtipo é especialmente valioso para cargas de trabalho de IA/ML em larga escala, como pesquisa de similaridade e armazenamento de inserção em que a eficiência de memória importa.

O suporte a vetor FLOAT16 é habilitado por meio da extensão de recurso de vetor já existente (identificador FE 0x0E) com um handshake de versão 2: o cliente solicita v2 por meio da propriedade vectorTypeSupport de conexão, e o servidor reconhece a funcionalidade FLOAT16 na resposta de recurso-ack.

Para usar vetores FLOAT16, siga os mesmos padrões mostrados nos exemplos anteriores e substitua FLOAT32 por FLOAT16 e o valor de escala 4 por 2. Por exemplo:

  • Use Vector.VectorDimensionType.FLOAT16 em vez de Vector.VectorDimensionType.FLOAT32.
  • Use uma escala de 2 em vez de 4 ao construir um vetor com precisão e escala.
  • Defina colunas SQL como vector(3, float16) em vez de vector(3).

Aqui está um exemplo de criação de um objeto de vetor 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});

Compatibilidade com versões anteriores

Se um aplicativo não for atualizado para lidar com o tipo de dados de vetor , o driver fornecerá compatibilidade com versões anteriores, permitindo que os tipos de dados de vetor sejam lidos como tipos compatíveis com versões anteriores. Esse comportamento é controlado com a propriedade vectorTypeSupport da string de conexão. Os valores com suporte são off (o servidor envia tipos de vetor como dados de cadeia de caracteres no formato JSON), v1 (o servidor envia tipos de vetor de FLOAT32 como dados de vetor) e v2 (para habilitar o suporte de tipo de vetor para FLOAT16). O valor padrão é v1.

Limitações do vetor

Para obter limitações detalhadas, consulte limitações de tipo de dados vetor.

Noções básicas sobre os tipos de dados do driver JDBC