Todos los productos
Search
Centro de documentos

Tablestore:Escritura de datos vectoriales

Última actualización: Sep 03, 2026

Las tablas de datos admiten la escritura de datos vectoriales en formatos de cadena y binario. El formato de cadena ofrece mayor legibilidad y facilita la resolución de problemas, mientras que el formato binario reduce los costos de almacenamiento.

Requisitos previos

Debe haber convertido contenido, como imágenes, videos y texto, en datos vectoriales mediante un Large Language Model (LLM). Para obtener más información, consulte Generate vectors.

Formato binario

Almacenar datos vectoriales en formato binario consume menos espacio en disco y reduce los costos de almacenamiento. En escenarios sensibles al costo con dimensiones vectoriales altas, escriba los datos vectoriales en formato binario.

Para escribir datos vectoriales en formato binario, convierta los vectores a datos binarios mediante el SDK de Tablestore o una herramienta.

Importante
  • Incluso cuando se escriben en formato binario, los vectores conservan el tipo Float32.

  • Los vectores se almacenan en la tabla de datos en formato binario y también se leen como datos binarios. Para mejorar la legibilidad, utilice una clase de utilidad para convertirlos al formato de cadena.

Conversión a binario mediante el SDK de Tablestore

Nota

A partir de la versión 5.17.6 del SDK de Java y la versión 6.2.1 del SDK de Python, Tablestore admite la conversión binaria de datos vectoriales mediante la clase de utilidad VectorUtils.

import com.alicloud.openservices.tablestore.SyncClient;
import com.alicloud.openservices.tablestore.model.*;
import com.alicloud.openservices.tablestore.model.search.vector.VectorUtils;

import java.util.Random;
import java.util.UUID;

// Helper method to generate a random vector.
private static float[] generateRandomFloats(int length, Random random) {
    float[] result = new float[length];
    for (int i = 0; i < length; i++) {
        result[i] = random.nextFloat();
    }
    return result;
}

// Write data in batches.
private static void batchWriteRow(SyncClient tableStoreClient) throws Exception {
    
    Random random = new Random();
    // Write 1,000 rows of data in batches of 100 rows.
    for (int i = 0; i < 10; i++) {
        BatchWriteRowRequest batchWriteRowRequest = new BatchWriteRowRequest();
        for (int j = 0; j < 100; j++) {
            // Your business data.
            String text = "A string for full-text search. An embedding vector is generated from this field and written to the field_vector field below for vector semantic similarity search";
            // The converted vector. Perform the conversion.
            float[] vector = generateRandomFloats(1024,random);
            RowPutChange rowPutChange = new RowPutChange("TABLE_NAME");
            // Set the primary key.
            rowPutChange.setPrimaryKey(PrimaryKeyBuilder.createPrimaryKeyBuilder().addPrimaryKeyColumn("PK_1", PrimaryKeyValue.fromString(UUID.randomUUID().toString())).build());
            // Set attribute columns.
            rowPutChange.addColumn("field_string", ColumnValue.fromLong(i));
            rowPutChange.addColumn("field_long", ColumnValue.fromLong(i * 100 + j));
            rowPutChange.addColumn("field_text", ColumnValue.fromString(text));
            // Write vector data in binary format.
            rowPutChange.addColumn("field_vector", ColumnValue.fromBinary(VectorUtils.toBytes(vector)));

            batchWriteRowRequest.addRowChange(rowPutChange);
        }
        BatchWriteRowResponse batchWriteRowResponse = tableStoreClient.batchWriteRow(batchWriteRowRequest);
        System.out.println("Batch write successful: " + batchWriteRowResponse.isAllSucceed());
        if (!batchWriteRowResponse.isAllSucceed()) {
            for (BatchWriteRowResponse.RowResult rowResult : batchWriteRowResponse.getFailedRows()) {
                System.out.println("Failed row: " + batchWriteRowRequest.getRowChange(rowResult.getTableName(), rowResult.getIndex()).getPrimaryKey());
                System.out.println("Failure reason: " + rowResult.getError());
            }
        }
    }
}
import time
import tablestore.utils
from tablestore import *

def batch_write_vector(rows_count):
    print('Begin prepare data: %d' % rows_count)
    batch_write_row_reqs = BatchWriteRowRequest()
    put_row_items = []
    for i in range(rows_count):
        pk = [('PK1', i)]

        cols = [('field_string', 'key%03d' % i),
                ('field_long', i),
                ('field_text', 'some text'),
                ('field_vector', tablestore.utils.VectorUtils.floats_to_bytes([0.1, 0.2, 0.3, 0.4]))]

        put_row_item = PutRowItem(Row(pk,cols),Condition(RowExistenceExpectation.IGNORE))
        put_row_items.append(put_row_item)
    batch_write_row_reqs.add(TableInBatchWriteRowItem(table_name, put_row_items))
    client.batch_write_row(batch_write_row_reqs)

    print('End prepare data.')
    print('Wait for data sync to search index.')
    time.sleep(60)

Conversión a binario mediante una herramienta

public class VectorUtils {
    private static final ByteOrder order = ByteOrder.LITTLE_ENDIAN;

    /**
     * Converts a float[] array to binary format.
     * @param vector The vector to convert.
     * @return byte The data in binary format.
     */
    public static byte[] toBytes(float[] vector) {
        if (vector == null || vector.length == 0) {
            throw new ClientException("vector is null or empty");
        }
        ByteBuffer buffer = ByteBuffer.allocate(vector.length * 4);
        buffer.order(order);
        for (float value : vector) {
            buffer.putFloat(value);
        }
        return buffer.array();
    }

    /**
     * Converts data from binary format back to a float[] array.
     * @param bytes The data in binary format.
     * @return Float The original vector.
     */
    public static float[] toFloats(byte[] bytes) {
        int length = bytes.length / 4;
        if (bytes.length % 4 != 0 || length == 0) {
            throw new ClientException("bytes length is not multiple of 4(SIZE_OF_FLOAT32) or length is 0");
        }
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        buffer.order(order);
        float[] vector = new float[length];
        buffer.asFloatBuffer().get(vector);
        return vector;
    }
}
// Float32ToBytes converts a []float32 slice to a byte array.
func Float32ToBytes(vector []float32) ([]byte, error) {
	if len(vector) == 0 {
		return nil, errors.New("vector is null or empty")
	}
	data := make([]byte, 4*len(vector))

	for i, v := range vector {
		binary.LittleEndian.PutUint32(data[i*4:(i+1)*4], math.Float32bits(v))
	}
	return data, nil
}

// ToFloat32 converts a byte array back to a []float32 slice.
func ToFloat32(data []byte) ([]float32, error) {
	if data == nil {
		return nil, errors.New("bytes is null")
	}
	if len(data)%4 != 0 || len(data) == 0 {
		return nil, errors.New("bytes length is not multiple of 4(SIZE_OF_FLOAT32) or length is 0")
	}
	floats := make([]float32, len(data)/4)
	buf := bytes.NewReader(data)

	for i := range floats {
		if err := binary.Read(buf, binary.LittleEndian, &floats[i]); err != nil {
			return nil, err
		}
	}

	return floats, nil
}
class VectorUtils:
    # Converts floats to a bytearray.
    @staticmethod
    def floats_to_bytes(floats):
        if not isinstance(floats, (list, tuple)) or not all(isinstance(f, float) for f in floats):
            raise TypeError("Input must be a list/tuple of floats")
        if len(floats) == 0:
            raise ValueError("vector is empty")
        return bytearray(struct.pack('<' + 'f' * len(floats), *floats))
      
    # Converts a bytearray back to floats.
    @staticmethod
    def bytes_to_floats(byte_data):
        if not isinstance(byte_data, bytearray):
            raise TypeError("Input must be a bytearray object")
        num_floats = len(byte_data) // 4
        if len(byte_data) % 4 != 0 or num_floats == 0:
            raise ValueError("bytes length is not multiple of 4(SIZE_OF_FLOAT32) or length is 0")
        floats = struct.unpack('<' + 'f' * num_floats, byte_data)
        return list(floats)

Comprobación de la conversión

El ejemplo a continuación del SDK de Java comprueba la conversión entre datos vectoriales y datos binarios. La conversión es correcta si el arreglo de números de punto flotante convertido es idéntico al arreglo original.

public class VectorUtilsTest {
    public static void main(String[] args) {
        float[] vector = new float[] { 1, 2, 3, 4 };
        byte[] bytes = VectorUtils.toBytes(vector);
        System.out.println("Converted binary data: " + Arrays.toString(bytes));
        float[] newVector = VectorUtils.toFloats(bytes);
        System.out.println("Converted floating-point number array: " + Arrays.toString(newVector));
    }
}

Formato de cadena

Almacenar vectores en formato de cadena ocupa más espacio en disco, pero ofrece mayor legibilidad. Para escribir datos vectoriales en formato de cadena, convierta el arreglo Float32 en una cadena JSON, como [0.1,0.2,0.3,0.4].

El ejemplo a continuación del SDK de Java escribe datos vectoriales en formato de cadena.

// Write data in batches.
private static void batchWriteRow(SyncClient tableStoreClient) throws Exception {
    // Write 1,000 rows of data in batches of 100 rows.
    for (int i = 0; i < 10; i++) {
        BatchWriteRowRequest batchWriteRowRequest = new BatchWriteRowRequest();
        for (int j = 0; j < 100; j++) {
            // Your business data.
            String text = "A string for full-text search. An embedding vector is generated from this field and written to the field_vector field below for vector semantic similarity search";
            // Convert text to a vector.
            String vector = "[1, 2, 3, 4]";
            RowPutChange rowPutChange = new RowPutChange("TABLE_NAME");
            // Set the primary key.
            rowPutChange.setPrimaryKey(PrimaryKeyBuilder.createPrimaryKeyBuilder().addPrimaryKeyColumn("PK_1", PrimaryKeyValue.fromString(UUID.randomUUID().toString())).build());
            // Set attribute columns.
            rowPutChange.addColumn("field_string", ColumnValue.fromLong(i));
            rowPutChange.addColumn("field_long", ColumnValue.fromLong(i * 100 + j));
            rowPutChange.addColumn("field_text", ColumnValue.fromString(text));
            // The vector format is a string of a float32 array, for example, [1, 5.1, 4.7, 0.08 ].
            rowPutChange.addColumn("field_vector", ColumnValue.fromString(vector));

            batchWriteRowRequest.addRowChange(rowPutChange);
        }
        BatchWriteRowResponse batchWriteRowResponse = tableStoreClient.batchWriteRow(batchWriteRowRequest);
        System.out.println("Batch write successful: " + batchWriteRowResponse.isAllSucceed());
        if (!batchWriteRowResponse.isAllSucceed()) {
            for (BatchWriteRowResponse.RowResult rowResult : batchWriteRowResponse.getFailedRows()) {
                System.out.println("Failed row: " + batchWriteRowRequest.getRowChange(rowResult.getTableName(), rowResult.getIndex()).getPrimaryKey());
                System.out.println("Failure reason: " + rowResult.getError());
            }
        }
    }
}