Todos os produtos
Search
Central de documentação

Tablestore:Get started with secondary indexes by using Tablestore SDKs

Última atualização: Jul 03, 2026

Um índice secundário permite consultar linhas usando colunas diferentes da chave primária de uma tabela de dados. Quando uma consulta baseada apenas na chave primária não recupera os dados necessários de forma eficiente, crie um índice secundário nas colunas predefinidas relevantes para acelerar as buscas. Após criar o índice, consulte-o diretamente em vez de varrer toda a tabela de dados.

Pré-requisitos

Antes de começar, verifique se:

  • O parâmetro Max Versions da tabela de dados está definido como 1.

  • O TTL da tabela de dados está definido como -1 (os dados nunca expiram) ou o parâmetro Allow Updates está definido como No.

Nota

O TTL de um índice secundário é igual ao TTL da tabela de dados.

Etapa 1: (Opcional) Gerencie colunas predefinidas

Um índice secundário só pode usar colunas declaradas como colunas predefinidas durante a criação da tabela de dados. Se a tabela não tiver colunas predefinidas ou se as existentes não atenderem às suas necessidades de indexação, adicione ou remova colunas predefinidas antes de criar o índice.

Os exemplos abaixo usam o SDK do Tablestore para Java. O SDK do Tablestore para Go também é compatível.

Adicionar uma coluna predefinida

Método

public AddDefinedColumnResponse addDefinedColumn(AddDefinedColumnRequest addDefinedColumnRequest) throws TableStoreException, ClientException

Parâmetros

Parameter

Type

Description

tableName (required)

String

Nome da tabela de dados.

definedColumns (required)

List

Informações das colunas predefinidas. Cada coluna predefinida contém os seguintes parâmetros:

  • name (String, required): nome da coluna predefinida.

  • type (DefinedColumnType, required): tipo de dado da coluna predefinida. Valores válidos: STRING, INTEGER, BINARY, DOUBLE e BOOLEAN.

Código de exemplo

O exemplo a seguir adiciona uma coluna predefinida do tipo String chamada name à tabela test_table.

public static void addDefinedColumnExample(SyncClient client) {
    AddDefinedColumnRequest addDefinedColumnRequest = new AddDefinedColumnRequest();
    addDefinedColumnRequest.setTableName("test_table");
    addDefinedColumnRequest.addDefinedColumn("name", DefinedColumnType.STRING);
    client.addDefinedColumn(addDefinedColumnRequest);
}

Exclua uma coluna predefinida

Método

public DeleteDefinedColumnResponse deleteDefinedColumn(DeleteDefinedColumnRequest deleteDefinedColumnRequest) throws TableStoreException, ClientException

Parâmetros

Parameter

Type

Description

tableName (required)

String

Nome da tabela de dados.

definedColumns (required)

List<String>

Nomes das colunas predefinidas a serem excluídas.

Código de exemplo

O exemplo a seguir exclui a coluna predefinida chamada name da tabela test_table.

public static void deleteDefinedColumnExample(SyncClient client) {
    DeleteDefinedColumnRequest deleteDefinedColumnRequest = new DeleteDefinedColumnRequest();
    deleteDefinedColumnRequest.setTableName("test_table");
    deleteDefinedColumnRequest.addDefinedColumn("name");
    client.deleteDefinedColumn(deleteDefinedColumnRequest);
}

Etapa 2: Crie um índice secundário

Chame a operação CreateIndex para criar uma tabela de índice para uma tabela de dados existente e acelerar consultas. Os índices secundários classificam-se em globais e locais. Crie um índice secundário global ou local conforme os requisitos do seu negócio.

Nota

Também é possível criar uma ou mais tabelas de índice simultaneamente à tabela de dados chamando a operação CreateTable. Para mais informações, consulte Criar uma tabela de dados.

Os exemplos abaixo usam o SDK do Tablestore para Java. Os seguintes SDKs também são compatíveis: Go, Python, Node.js, .NET e PHP.

Crie um índice secundário global

O exemplo a seguir cria um índice secundário global. O índice usa DEFINED_COL_NAME_1 como primeira coluna de chave primária e PRIMARY_KEY_NAME_2 como segunda. A coluna DEFINED_COL_NAME_2 é incluída como coluna de atributo para permitir leitura direta do índice, sem necessidade de consultar a tabela de dados.

Defina IncludeBaseData como true para incluir as linhas existentes da tabela de dados no índice. O tempo necessário para preencher os dados existentes varia conforme o volume de dados.

private static void createIndex(SyncClient client) {
    IndexMeta indexMeta = new IndexMeta("<INDEX_NAME>");
    // Set DEFINED_COL_NAME_1 as the first primary key column of the index.
    indexMeta.addPrimaryKeyColumn(DEFINED_COL_NAME_1);
    // Set PRIMARY_KEY_NAME_2 as the second primary key column of the index.
    indexMeta.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
    // Include DEFINED_COL_NAME_2 as an attribute column for direct reads from the index.
    indexMeta.addDefinedColumn(DEFINED_COL_NAME_2);
    // Create the index without backfilling existing data.
    // Set the third parameter to true to include existing data.
    CreateIndexRequest request = new CreateIndexRequest("<TABLE_NAME>", indexMeta, false);
    client.createIndex(request);
}

Crie um índice secundário local

O exemplo a seguir cria um índice secundário local. A primeira coluna de chave primária do índice (PRIMARY_KEY_NAME_1) deve corresponder à primeira coluna de chave primária da tabela de dados. O tipo de índice é definido como IT_LOCAL_INDEX e o modo de atualização como IUM_SYNC_INDEX (atualização síncrona).

Defina IncludeBaseData como true para incluir as linhas existentes da tabela de dados no índice. O tempo necessário para preencher os dados existentes varia conforme o volume de dados.

private static void createIndex(SyncClient client) {
    IndexMeta indexMeta = new IndexMeta("<INDEX_NAME>");
    // The first primary key column of a local secondary index must match
    // the first primary key column of the data table.
    indexMeta.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1);
    indexMeta.addPrimaryKeyColumn(DEFINED_COL_NAME_1);
    indexMeta.addDefinedColumn(DEFINED_COL_NAME_2);
    indexMeta.setIndexType(IT_LOCAL_INDEX);
    indexMeta.setIndexUpdateMode(IUM_SYNC_INDEX);
    // Create the index without backfilling existing data.
    // Set the third parameter to true to include existing data.
    CreateIndexRequest request = new CreateIndexRequest("<TABLE_NAME>", indexMeta, false);
    client.createIndex(request);
}

Etapa 3: Ler dados da tabela de índice

O caminho de leitura depende das colunas de atributo necessárias:

  • Colunas presentes na tabela de índice: leia diretamente da tabela de índice.

  • Colunas ausentes na tabela de índice: varra a tabela de índice para obter a chave primária de cada linha correspondente e busque essas colunas na tabela de dados. Essa abordagem em duas etapas gera uma leitura extra por linha; portanto, inclua as colunas de atributo consultadas frequentemente no índice durante a criação.

Os exemplos abaixo usam o SDK do Tablestore para Java. Os seguintes SDKs também são compatíveis: Go, Python, Node.js, .NET e PHP.

Ler uma única linha

Construa a chave primária da tabela de índice e chame getRow. O exemplo a seguir lê uma única linha e, em seguida, executa outra leitura com um filtro de coluna específico.

private static void getRowFromIndex(SyncClient client) {
    // Build the primary key of the index table.
    // For a local secondary index, the first primary key column must match
    // the first primary key column of the data table.
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.fromString("def1"));
    primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.fromLong(100));
    primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.fromString("pri1"));
    PrimaryKey primaryKey = primaryKeyBuilder.build();

    SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("<INDEX_NAME>", primaryKey);
    criteria.setMaxVersions(1);
    GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
    Row row = getRowResponse.getRow();
    // Returns null if the row does not exist.
    System.out.println("Read result: " + row);

    // Read a specific column.
    criteria.addColumnsToGet("Col0");
    getRowResponse = client.getRow(new GetRowRequest(criteria));
    row = getRowResponse.getRow();
    System.out.println("Read result: " + row);
}

Ler um intervalo de linhas

Defina uma chave primária inicial e final na tabela de índice e chame getRange em um loop até que nextStartPrimaryKey seja nulo.

Usar um índice secundário global

Quando todas as colunas necessárias estiverem na tabela de índice, leia diretamente do índice.

private static void scanFromIndex(SyncClient client) {
    RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria("<INDEX_NAME>");

    PrimaryKeyBuilder startPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    startPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MIN);
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MIN);
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MIN);
    rangeRowQueryCriteria.setInclusiveStartPrimaryKey(startPrimaryKeyBuilder.build());

    PrimaryKeyBuilder endPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    endPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MAX);
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MAX);
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MAX);
    rangeRowQueryCriteria.setExclusiveEndPrimaryKey(endPrimaryKeyBuilder.build());

    rangeRowQueryCriteria.setMaxVersions(1);

    System.out.println("Scan result of the index table:");
    while (true) {
        GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria));
        for (Row row : getRangeResponse.getRows()) {
            System.out.println(row);
        }
        if (getRangeResponse.getNextStartPrimaryKey() != null) {
            rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey());
        } else {
            break;
        }
    }
}

Quando as colunas necessárias não estiverem na tabela de índice, varra o índice para obter a chave primária de cada linha correspondente e busque essas colunas na tabela de dados.

private static void scanFromIndex(SyncClient client) {
    RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria("<INDEX_NAME>");

    PrimaryKeyBuilder startPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    startPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MIN);
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MIN);
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MIN);
    rangeRowQueryCriteria.setInclusiveStartPrimaryKey(startPrimaryKeyBuilder.build());

    PrimaryKeyBuilder endPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    endPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MAX);
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MAX);
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MAX);
    rangeRowQueryCriteria.setExclusiveEndPrimaryKey(endPrimaryKeyBuilder.build());

    rangeRowQueryCriteria.setMaxVersions(1);

    while (true) {
        GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria));
        for (Row row : getRangeResponse.getRows()) {
            // Extract the data table primary key from the index row.
            PrimaryKey curIndexPrimaryKey = row.getPrimaryKey();
            PrimaryKeyColumn pk1 = curIndexPrimaryKey.getPrimaryKeyColumn(PRIMARY_KEY_NAME_1);
            PrimaryKeyColumn pk2 = curIndexPrimaryKey.getPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
            PrimaryKeyBuilder mainTablePKBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
            mainTablePKBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, pk1.getValue());
            mainTablePKBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, pk2.getValue());
            PrimaryKey mainTablePK = mainTablePKBuilder.build();

            // Fetch the required columns from the data table.
            SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("<TABLE_NAME>", mainTablePK);
            criteria.addColumnsToGet(DEFINED_COL_NAME_3);
            criteria.setMaxVersions(1);
            GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
            Row mainTableRow = getRowResponse.getRow();
            System.out.println(row);
        }
        if (getRangeResponse.getNextStartPrimaryKey() != null) {
            rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey());
        } else {
            break;
        }
    }
}

Usar um índice secundário local

Quando todas as colunas necessárias estiverem na tabela de índice, leia diretamente do índice.

private static void scanFromIndex(SyncClient client) {
    RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria("INDEX_NAME");

    PrimaryKeyBuilder startPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MIN);
    startPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MIN);
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MIN);
    rangeRowQueryCriteria.setInclusiveStartPrimaryKey(startPrimaryKeyBuilder.build());

    PrimaryKeyBuilder endPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MAX);
    endPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MAX);
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MAX);
    rangeRowQueryCriteria.setExclusiveEndPrimaryKey(endPrimaryKeyBuilder.build());

    rangeRowQueryCriteria.setMaxVersions(1);

    System.out.println("Scan result of the index table:");
    while (true) {
        GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria));
        for (Row row : getRangeResponse.getRows()) {
            System.out.println(row);
        }
        if (getRangeResponse.getNextStartPrimaryKey() != null) {
            rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey());
        } else {
            break;
        }
    }
}

Quando as colunas necessárias não estiverem na tabela de índice, varra o índice para obter a chave primária de cada linha correspondente e busque essas colunas na tabela de dados.

private static void scanFromIndex(SyncClient client) {
    RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria("<INDEX_NAME>");

    PrimaryKeyBuilder startPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MIN);
    startPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MIN);
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MIN);
    rangeRowQueryCriteria.setInclusiveStartPrimaryKey(startPrimaryKeyBuilder.build());

    PrimaryKeyBuilder endPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MAX);
    endPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MAX);
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MAX);
    rangeRowQueryCriteria.setExclusiveEndPrimaryKey(endPrimaryKeyBuilder.build());

    rangeRowQueryCriteria.setMaxVersions(1);

    while (true) {
        GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria));
        for (Row row : getRangeResponse.getRows()) {
            // Extract the data table primary key from the index row.
            PrimaryKey curIndexPrimaryKey = row.getPrimaryKey();
            PrimaryKeyColumn pk1 = curIndexPrimaryKey.getPrimaryKeyColumn(PRIMARY_KEY_NAME_1);
            PrimaryKeyColumn pk2 = curIndexPrimaryKey.getPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
            PrimaryKeyBuilder mainTablePKBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
            mainTablePKBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, pk1.getValue());
            mainTablePKBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, pk2.getValue());
            PrimaryKey mainTablePK = mainTablePKBuilder.build();

            // Fetch the required columns from the data table.
            SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("TABLE_NAME", mainTablePK);
            criteria.addColumnsToGet(DEFINED_COL_NAME3);
            criteria.setMaxVersions(1);
            GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
            Row mainTableRow = getRowResponse.getRow();
            System.out.println(row);
        }
        if (getRangeResponse.getNextStartPrimaryKey() != null) {
            rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey());
        } else {
            break;
        }
    }
}

Apêndice: Exclua uma tabela de índice

Exclua uma tabela de índice quando ela não for mais necessária.

Os exemplos abaixo usam o SDK do Tablestore para Java. Os seguintes SDKs também são compatíveis: Go, Python, Node.js, .NET e PHP.

private static void deleteIndex(SyncClient client) {
    DeleteIndexRequest request = new DeleteIndexRequest("<TABLE_NAME>", "<INDEX_NAME>");
    client.deleteIndex(request);
}

Perguntas frequentes

Referências

  • Use índices secundários no console do Tablestore ou no CLI do Tablestore. Para mais informações, consulte Usar índices secundários no console do Tablestore e Índice secundário.

  • Para opções de consulta mais flexíveis — incluindo pesquisa de texto completo, consulta booleana, consulta de prefixo e consulta difusa — use o recurso de índice de pesquisa. Para mais informações, consulte Visão geral.