如何在Google Spanner的readUsingIndex方法中指定WHERE条件?
在Google Spanner的readUsingIndex中指定WHERE条件
你完全不需要在遍历ResultSet的时候手动过滤行!Google Spanner的Java客户端提供了两种直接在读取阶段指定过滤条件的方式,适配不同的场景:
1. 针对索引主键列的简单过滤(用KeySet)
readUsingIndex方法是基于索引的键来实现高效读取的,所以如果你的WHERE条件是针对索引的主键列(也就是你创建AlbumsByAlbumTitle2时指定的索引列,比如AlbumTitle),可以通过KeySet来精准指定过滤规则:
示例1:精确匹配某值
比如要查询AlbumTitle = 'Thriller'的行,替换原来的KeySet.all()为KeySet.singleKey():
static void readStoringIndexWithExactMatch(DatabaseClient dbClient) { try (ResultSet resultSet = dbClient .singleUse() .readUsingIndex( "Albums", "AlbumsByAlbumTitle2", // 对应WHERE AlbumTitle = 'Thriller' KeySet.singleKey(Key.of("Thriller")), Arrays.asList("AlbumId", "AlbumTitle", "MarketingBudget"))) { while (resultSet.next()) { System.out.printf( "%d %s %s\n", resultSet.getLong(0), resultSet.getString(1), resultSet.isNull("MarketingBudget") ? "NULL" : resultSet.getLong("MarketingBudget")); } } }
示例2:范围匹配
如果要查询AlbumTitle介于"Acoustic"和"Jazz"之间的行,可以用KeySet.range():
static void readStoringIndexWithRange(DatabaseClient dbClient) { // 对应WHERE AlbumTitle >= 'Acoustic' AND AlbumTitle <= 'Jazz' KeySet keySet = KeySet.range() .start(Key.of("Acoustic")) .end(Key.of("Jazz")) .build(); try (ResultSet resultSet = dbClient .singleUse() .readUsingIndex( "Albums", "AlbumsByAlbumTitle2", keySet, Arrays.asList("AlbumId", "AlbumTitle", "MarketingBudget"))) { while (resultSet.next()) { System.out.printf( "%d %s %s\n", resultSet.getLong(0), resultSet.getString(1), resultSet.isNull("MarketingBudget") ? "NULL" : resultSet.getLong("MarketingBudget")); } } }
2. 复杂条件过滤(用SQL查询+强制索引)
如果你的WHERE条件涉及非索引主键列(比如MarketingBudget),或者需要更复杂的逻辑(AND/OR组合、比较运算符等),直接使用SQL查询会更灵活,同时可以通过@{FORCE_INDEX=索引名}来强制Spanner使用你指定的存储索引,保证读取效率:
static void queryWithComplexCondition(DatabaseClient dbClient) { String sql = "SELECT AlbumId, AlbumTitle, MarketingBudget " + "FROM Albums@{FORCE_INDEX=AlbumsByAlbumTitle2} " + "WHERE MarketingBudget > 10000 AND AlbumTitle LIKE 'Rock%'"; try (ResultSet resultSet = dbClient.singleUse().executeQuery(Statement.of(sql))) { while (resultSet.next()) { System.out.printf( "%d %s %s\n", resultSet.getLong(0), resultSet.getString(1), resultSet.isNull("MarketingBudget") ? "NULL" : resultSet.getLong("MarketingBudget")); } } }
总结
- 简单的索引列过滤:用
KeySet配合readUsingIndex,性能最优; - 复杂条件或非索引列过滤:用SQL查询+强制索引,灵活性更高。
内容的提问来源于stack exchange,提问作者Aditya Rewari
相关产品推荐
相关产品推荐

