创建索引的两种方式(重点)

本文深入探讨了SQL中自动与手动创建索引的策略,包括哪些列适合建索引及其存在意义,同时列举了导致索引用不了的情况及避免方法。重点突出通过合理利用索引来提升查询效率的重要性。

① 自动创建索引:当创建 uniquepk 约束时,索引自动创建。


② 手动创建索引:

create index emp_ename_index on emp(ename);

哪些列适合建索引

经常出现在where子句的列。

经常用于表连接的列。

该列包含许多null值。

表很大,查询的结果集却很小。

pk列和unique列。

fk列。

经常需要排序和分组的列。

索引的存在意义在于提高查询效率。

最后注意:索引不是万能的。

哪些列不适合建索引

表很小。

列很少出现在where子句。

查询的结果集很大。

该列经常被更新。

哪些写法会导致索引用不了

① 函数导致索引用不了

where upper(first_name)=' tom ;

② 表达式导致索引用不了

where sal*12=18000 ;

③ 部分隐式数据类型导致索引用不了

where c1=2( c1为varchar2类型 ) ;

④ like

where first_name like 'CA%' ;

⑤ 否定形式导致索引用不了

where first_name<>' tom ' ;

where sal not between 1000 and 2000 ;

where deptno not in(10,20,30) ;

⑥ is null导致索引用不了

where comm is null ;






<think>我们正在使用ApacheIgnite,并且需要在Java代码中创建索引。根据之前的问题,我们知道用户在使用Ignite2.17.0,并遇到了配置合并的问题。但本次问题是如何在Java代码中创建索引。在Ignite中,创建索引两种主要方式:1.使用SQL语句(DDL)创建索引。2.通过JavaAPI配置索引(在缓存配置中定义索引,然后在创建缓存时使用该配置)。由于用户询问的是Java代码中创建索引的方法,我们将重点放在这两种方式的Java代码实现上。根据引用[4],我们知道Ignite的索引依赖于H2数据库,并且SQL引擎与H2绑定。因此,我们可以使用SQL语句在Java代码中执行。此外,我们还可以在缓存配置中预先定义索引。下面分别给出示例:###方法1:使用SQL语句在Java代码中创建索引我们可以通过Ignite的SQLAPI执行CREATEINDEX语句。示例代码:```javaimportorg.apache.ignite.Ignite;importorg.apache.ignite.Ignition;importorg.apache.ignite.configuration.IgniteConfiguration;publicclassCreateIndexViaSQL{publicstaticvoidmain(String[]args){//启动Ignite节点(如果已经启动则获取实例)Igniteignite=Ignition.start();//执行SQL语句创建索引ignite.sql().execute("CREATEINDEXIFNOTEXISTSidx_user_idONClientImage(userId)");//或者创建复合索引ignite.sql().execute("CREATEINDEXidx_user_statusONClientImage(userId,status)INLINE_SIZE64");//注意:表名(这里使用缓存名)必须存在,否则会报错}}```###方法2:在缓存配置中定义索引创建缓存之前,我们可以通过`CacheConfiguration`来配置索引。这种方式适用于在创建缓存的同时定义索引。示例代码:```javaimportorg.apache.ignite.Ignite;importorg.apache.ignite.Ignition;importorg.apache.ignite.cache.CacheMode;importorg.apache.ignite.cache.QueryIndex;importorg.apache.ignite.cache.QueryIndexType;importorg.apache.ignite.configuration.CacheConfiguration;importorg.apache.ignite.configuration.IgniteConfiguration;importjava.util.Arrays;publicclassCreateIndexViaCacheConfig{publicstaticvoidmain(String[]args){IgniteConfigurationcfg=newIgniteConfiguration();//其他节点配置...//启动节点Igniteignite=Ignition.start(cfg);//创建缓存配置CacheConfiguration<Long,ClientImage>cacheCfg=newCacheConfiguration<>("ClientImage");//配置索引QueryIndexidxUserId=newQueryIndex("userId",QueryIndexType.SORTED);QueryIndexidxUserStatus=newQueryIndex("userId","status");//默认是SORTED类型//设置索引(可以设置多个)cacheCfg.setIndexedTypes(Long.class,ClientImage.class);//注意:这里需要设置索引类型,即键值的类型cacheCfg.setQueryEntities(Arrays.asList(//定义QueryEntity,其中可以指定索引//但更简单的方式是使用注解或直接在类上配置));//或者直接通过QueryIndex设置(推荐)cacheCfg.setQueryIndices(Arrays.asList(idxUserId,idxUserStatus));//创建缓存ignite.getOrCreateCache(cacheCfg);}//定义ClientImage类(需要实现Serializable)publicstaticclassClientImageimplementsSerializable{privatelonguserId;privateStringstatus;//...其他字段、getter、setter}}```注意:在方法2中,我们通常使用`QueryIndex`来定义索引。另外,我们需要指定被索引字段的类型映射,这可以通过`setIndexedTypes`或`setTypeMetadata`等方法完成。但是,更常见的做法是使用注解来标记索引字段(例如`@QuerySqlField(index=true)`)。因此,我们也可以使用注解的方式来定义索引:###方法3:使用注解定义索引(结合缓存配置)首先,在值对象的字段上添加注解:```javaimportorg.apache.ignite.cache.query.annotations.QuerySqlField;publicclassClientImageimplementsSerializable{@QuerySqlField(index=true)privatelonguserId;@QuerySqlFieldprivateStringstatus;@QuerySqlField(index=true,descending=true)//可以指定降序privateDatecreatedDate;//复合索引需要在一个内联字段上定义,或者通过QueryIndex组合//但注意:注解方式定义复合索引需要在类上使用@QuerySqlField.Group@QuerySqlField(index=true,groups={@QuerySqlField.Group(name="user_status",order=0)})privatelonggroupUserId;//假设是复合索引的一部分@QuerySqlField(index=true,groups={@QuerySqlField.Group(name="user_status",order=1)})privateStringgroupStatus;//...getter、setter}```然后在缓存配置中,我们只需要设置类型,索引自动根据注解创建:```javaCacheConfiguration<Long,ClientImage>cacheCfg=newCacheConfiguration<>("ClientImage");cacheCfg.setIndexedTypes(Long.class,ClientImage.class);//这里设置键类型值类型```注意:在创建缓存之后,我们还可以通过SQL语句添加索引(但需要确保表存在)。另外,在缓存已存在的情况下动态添加索引,建议使用SQL的CREATEINDEX语句(方法1)。###关于配置冲突的规避如果是在已存在的缓存上动态创建索引,要避免新节点加入时的配置合并问题,可以参考之前提供的方案(空配置启动节点,然后动态加载缓存配置并创建索引)。###注意事项-创建索引可能需要一些时间,特别是数据量大的时候。-在线创建索引(在已有数据的缓存上)可能会影响性能,建议在低峰期操作。下面是根据用户之前的上下文,我们可能需要考虑的安全创建索引步骤(避免配置合并问题):1.使用空缓存配置启动节点(`cfg.setCacheConfiguration()`设置为空数组)。2.节点加入集群后,动态获取缓存配置并创建缓存(如果缓存不存在)。3.使用SQLAPI执行索引创建语句。但是,在动态节点安全加入后,创建索引的步骤可以独立进行。由于用户询问的是创建索引,我们重点放在创建索引的方法上。现在,我们来生成相关问题。</think> ### Apache Ignite Java代码创建索引指南 在Java代码中为Apache Ignite创建索引主要有两种方式:通过SQL执行DDL语句通过缓存配置API。以下是具体实现方法: #### 方法1: 使用SQL API创建索引(推荐) ```java import org.apache.ignite.Ignite; import org.apache.ignite.Ignition; import org.apache.ignite.configuration.IgniteConfiguration; public class IgniteIndexCreator { public static void main(String[] args) { // 1. 启动Ignite节点 Ignite ignite = Ignition.start(new IgniteConfiguration()); // 2. 使用SQL创建索引 ignite.sql().execute( "CREATE INDEX IF NOT EXISTS idx_user ON ClientImage (userId) " + "INLINE_SIZE 64" // 优化参数:内联大小 ); // 3. 创建复合索引(多列) ignite.sql().execute( "CREATE INDEX idx_user_status ON ClientImage (userId, status) " + "PARALLEL 4" // 优化参数:并行度 ); System.out.println("索引创建完成"); } } ``` **关键特性**: - `INLINE_SIZE`:减少内存碎片[^4],公式:$$ \text{INLINE\_SIZE} \approx 2 \times \text{avg\_key} + \text{avg\_val} $$ - `PARALLEL`:加速索引创建(值=CPU核心数) - `IF NOT EXISTS`:避免重复创建冲突 #### 方法2: 通过缓存配置API创建索引 ```java import org.apache.ignite.cache.*; import org.apache.ignite.cache.query.annotations.*; CacheConfiguration<Long, ClientImage> cacheCfg = new CacheConfiguration<>("ClientImage"); // 1. 通过类注解定义索引 cacheCfg.setIndexedTypes(Long.class, ClientImage.class); // 触发注解扫描 // 值对象类定义 public class ClientImage { // 单字段索引 @QuerySqlField(index = true) private long userId; // 复合索引定义 @QuerySqlField( index = true, groups = @QuerySqlField.Group(name = "composite_idx", order = 0) ) private String status; } ``` #### 动态索引管理API ```java // 检查索引是否存在 if(!ignite.cache("ClientImage").queryMetrics().indexes().containsKey("idx_user")) { // 异步重建索引(避免阻塞) ignite.sql().execute( "ALTER INDEX ClientImage.idx_user REBUILD WITH (ASYNC=true)" ); // 监控重建进度 QueryMetrics metrics = ignite.cache("ClientImage").queryMetrics(); System.out.println("待重建索引数量: " + metrics.brokenIndexesCount()); } ``` #### 最佳实践 1. **索引验证**:使用Affinity API检测索引分布 ```java Affinity<Long> affinity = ignite.affinity("ClientImage"); ClusterNode node = affinity.mapKeyToNode(12345L); // 测试键分布 ``` [^3] 2. **配置一致性**:所有节点需使用相同Ignite版本(参考`ignite-core:2.11.0`)[^1] 3. **依赖配置**: ```xml <!-- 需包含SQL模块 --> <dependency> <groupId>org.apache.ignite</groupId> <artifactId>ignite-core</artifactId> <version>2.17.0</version> </dependency> <dependency> <groupId>org.apache.ignite</groupId> <artifactId>ignite-indexing</artifactId> <version>2.17.0</version> </dependency> ``` --- ### 性能优化建议 1. 使用`INLINE_SIZE`减少内存碎片 2. 对大表采用`PARALLEL`并行创建 3. 避免在线DDL:使用`ASYNC=true`重建索引 $$ \text{重建耗时} \approx \frac{\text{数据量}}{\text{节点数} \times \text{CPU核心数}} $$ 4. 定期监控`QueryMetrics.indexRebuildTime`指标 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值