The secondary index feature allows you to create an index on the specified columns. Data in the generated index table is sorted based on the specified index key columns. All data written to the data table is automatically synchronized to the index table. After you write data to the data table, you can query the data from the index table that is created for the data table. This improves the query efficiency.
Sample scenario
This topic describes how to use the secondary index feature to query phone records. When a phone call is complete, the information about the phone call is recorded in a data table.
The following section describes the primary key columns and predefined columns of the data table:
The CellNumber and StartTime columns are used as the primary key columns of the data table. Each value in the CellNumber column indicates a calling number, and each value in the StartTime column indicates the start time of a phone call.
The CalledNumber, Duration, and BaseStationNumber columns are used as the predefined columns of the data table. Each value in the CalledNumber column indicates a called number, each value in the Duration column indicates the duration of a phone call, and each value in the BaseStationNumber column indicates a base station number.
The following table provides the sample data in the data table. The Wide Column model of Tablestore sorts rows in a data table based on their primary keys and provides the GetRange operation to query data.
CellNumber | StartTime (UNIX timestamp) | CalledNumber | Duration | BaseStationNumber |
123456 | 1532574644 | 654321 | 60 | 1 |
234567 | 1532574714 | 765432 | 10 | 1 |
234567 | 1532574734 | 123456 | 20 | 3 |
345678 | 1532574795 | 123456 | 5 | 2 |
345678 | 1532574861 | 123456 | 100 | 2 |
456789 | 1532584054 | 345678 | 200 | 3 |
You can use data tables, global secondary indexes, or local secondary indexes to perform the following queries based on your business requirements:
Query the rows in which the value of the CellNumber column is 234567.
Query the rows in which the value of the CalledNumber column is 123456.
Query the rows in which the value of the BaseStationNumber column is 2 and the value of the StartTime column is 1532574740.
Query the values of the Duration column for the rows in which the value of the BaseStationNumber column is 3 and the value of the StartTime column ranges from 1532574861 to 1532584054.
Query the total, average, maximum, and minimum call duration of all phone calls forwarded by the base station 3. The value of the StartTime column ranges from 1532574861 to 1532584054.
Query the rows in which the value of the CellNumber column is 456789 and the value of the CalledNumber column is 345678.
Data queries
You can select an appropriate method to query data based on your query requirements.
Methods
The following table describes how to implement different queries.
For more information about the sample code that is used to create a data table and a secondary index table, see Appendix: Sample code for creating the data table and secondary index tables.
After you create a data table, you need to write sample data to the data table. The data in the data table is automatically synchronized to the index table created for the data table. For more information about how to write data, see Write data.
Tablestore automatically adds the primary key columns of a data table that are not specified as index key columns to the index table created for the data table. The primary key columns of the data table and the index key column are used as the primary key columns of the index table.
If you use a local secondary index, the first primary key column of the index table must be the same as the first primary key column of the data table for which the index table is created.
Query | Method |
Query the rows in which the value of the CellNumber column is 234567 | You can directly call the GetRange operation to scan the data table. |
Query the rows in which the value of the CalledNumber column is 123456 | You can create an index table based on the CalledNumber column and call the GetRange operation to scan the index table. |
Query the rows in which the value of the BaseStationNumber column is 2 and the value of the StartTime column is 1532574740 | You can create an index table based on the BaseStationNumber and StartTime columns and call the GetRange operation to scan the index table whose index type is global secondary index. |
Query the values of the Duration column for the rows in which the value of the BaseStationNumber column is 3 and the value of the StartTime column ranges from 1532574861 to 1532584054 | You can create an index table based on the BaseStationNumber and StartTime columns, specify that only the values of the Duration column are returned, and then call the GetRange operation to scan the index table whose index type is global secondary index. You can manually query the values of the Duration column from the data table or specify the Duration column as an attribute column of the index table. To query the total, average, maximum, and minimum call duration of all phone calls that are forwarded by the base station 3 and whose start time ranges from 1532574861 to 1532584054, you can also use this query method. Then, you can perform aggregation on the Duration column to obtain the final results. Note You can also execute SQL statements to obtain the results without client-side calculations. For more information, see Query data. |
Query the rows in which the value of the CellNumber column is 456789 and the value of the CalledNumber column is 345678 | You can create an index table based on the CellNumber and CalledNumber columns, specify the Duration and BaseStationNumber columns as the attribute columns of the index table, and then call the GetRange operation to scan the index table whose index type is local secondary index. |
Query the rows in which the value of the CellNumber column is 234567
Query the rows in which the value of the CalledNumber column is 123456
Query the rows in which the value of the BaseStationNumber column is 2 and the value of the StartTime column is 1532574740
Query the values of the Duration column for the rows in which the value of the BaseStationNumber column is 3 and the value of the StartTime column ranges from 1532574861 to 1532584054
Query the rows in which the value of the CellNumber column is 456789 and the value of the CalledNumber column is 345678
Appendix: Sample code for creating the data table and secondary index tables
The following sample code shows how to create the data table and secondary index tables used in this topic. The index types include local secondary index and global secondary index.
private static final String TABLE_NAME = "CallRecordTable";
private static final String INDEX0_NAME = "IndexOnBeCalledNumber";
private static final String INDEX1_NAME = "IndexOnBaseStation1";
private static final String INDEX2_NAME = "IndexOnBaseStation2";
private static final String INDEX3_NAME = "LocalIndexOnBeCalledNumber";
private static final String PRIMARY_KEY_NAME_1 = "CellNumber";
private static final String PRIMARY_KEY_NAME_2 = "StartTime";
private static final String DEFINED_COL_NAME_1 = "CalledNumber";
private static final String DEFINED_COL_NAME_2 = "Duration";
private static final String DEFINED_COL_NAME_3 = "BaseStationNumber";
private static void createTable(SyncClient client) {
TableMeta tableMeta = new TableMeta(TABLE_NAME);
tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema(PRIMARY_KEY_NAME_1, PrimaryKeyType.INTEGER));
tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema(PRIMARY_KEY_NAME_2, PrimaryKeyType.INTEGER));
tableMeta.addDefinedColumn(new DefinedColumnSchema(DEFINED_COL_NAME_1, DefinedColumnType.INTEGER));
tableMeta.addDefinedColumn(new DefinedColumnSchema(DEFINED_COL_NAME_2, DefinedColumnType.INTEGER));
tableMeta.addDefinedColumn(new DefinedColumnSchema(DEFINED_COL_NAME_3, DefinedColumnType.INTEGER));
// Specify the Time to Live (TTL) of data. Unit: seconds. The value -1 indicates that the data never expires. You must set the value of timeToLive to -1 if a data table has one or more index tables.
int timeToLive = -1;
// Specify the maximum number of data versions that can be retained. You must set the value of maxVersions to 1 if a data table has one or more index tables.
int maxVersions = 1;
TableOptions tableOptions = new TableOptions(timeToLive, maxVersions);
ArrayList<IndexMeta> indexMetas = new ArrayList<IndexMeta>();
IndexMeta indexMeta0 = new IndexMeta(INDEX0_NAME);
indexMeta0.addPrimaryKeyColumn(DEFINED_COL_NAME_1);
indexMetas.add(indexMeta0);
IndexMeta indexMeta1 = new IndexMeta(INDEX1_NAME);
indexMeta1.addPrimaryKeyColumn(DEFINED_COL_NAME_3);
indexMeta1.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
indexMetas.add(indexMeta1);
IndexMeta indexMeta2 = new IndexMeta(INDEX2_NAME);
indexMeta2.addPrimaryKeyColumn(DEFINED_COL_NAME_3);
indexMeta2.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
indexMeta2.addDefinedColumn(DEFINED_COL_NAME_2);
indexMetas.add(indexMeta2);
IndexMeta indexMeta3 = new IndexMeta(INDEX3_NAME);
indexMeta3.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1);
indexMeta3.addPrimaryKeyColumn(DEFINED_COL_NAME_1);
indexMeta3.addDefinedColumn(DEFINED_COL_NAME_2);
indexMeta3.addDefinedColumn(DEFINED_COL_NAME_3);
// Set the value of indexUpdateMode to IUM_SYNC_INDEX.
indexMeta3.setIndexUpdateMode(IUM_SYNC_INDEX);
// Set the value of indexType to IT_LOCAL_INDEX.
indexMeta3.setIndexType(IT_LOCAL_INDEX);
indexMetas.add(indexMeta3);
CreateTableRequest request = new CreateTableRequest(tableMeta, tableOptions, indexMetas);
client.createTable(request);
}