索引重建和删除

1. 索引重建

主要针对图数据(vertices或edges)与其索引信息不一致的场景,通过索引重建使索引信息与原始数据同步。

1.1 重建场景

  • 场景1. 创建索引时,已经有vertices和edges存在,在index_label表中增加元数据之后,需要对已存在的vertices或edges创建索引信息
  • 场景2. bulkLoad之后,新增加的vertices或edges有对应的index需要建立(是否存在这种场景?
  • 场景3. 用户手动重建某个索引
  • 场景4. 用户重建某个vertex label或者edge label的全部索引

1.2 设计

索引重建的前两种场景可以依赖场景3和场景4实现,因此实现rebuildIndex(SchemaElement schemaElement),作为索引重建场景的基本操作,功能为重建schemaElement(index label、vertex label或edge label)对应的所有索引,实现逻辑如下:

  • 若schema为index_label,重建该index_label代表的索引(单个);若schema为vertex_label,重建该vertex_label关联的索引(0-n个);若schema为edge_label,重建该edge_label关联的索引(0-n个)
  • 删除对应索引数据(具体实现见下面)
  • 根据不同index_type重新建立索引
  • index_type = secondary
  • index_type = search

index_type = secondary

resultset = SELECT * FROM vertices where LABEL = 'person';// 获取所有待重建索引的vertices或者edges
// 逐条建立索引
for(result :resultset)
    INSERT INTO secondary_indexes (PROPERTY_VALUES, INDEX_LABEL_NAME, ELEMENT_IDS) VALUE (x,y,z)

index_type = search

resultset = SELECT * FROM vertices where LABEL = 'person';// 获取所有待重建索引的vertices或者edges
// 逐条建立索引
for(result :resultset)
    INSERT INTO search_indexes (INDEX_LABEL_NAME, PROPERTY_VALUES, ELEMENT_IDS) VALUE (x,y,z)

1.3 其他要点

1.3.1 锁机制
  • 重建索引时,由于索引和数据会出现不一致,为保证正确性,应当加锁,禁止重建过程中,对重建索引的数据进行读取
  • 在程序架构中实现全局锁(单例模式实现),重建索引时禁止相应vertices或edges的查询
  • 索引构建时,允许写入vertices和edges。因为写入时会先后更新原始数据和索引信息,不会引起数据和索引的不一致

锁的创建操作:

  • 锁组(lockGroup)在hugegraph系统启动时创建,用于逻辑上规定锁的范围。具体的锁在使用时根据情况处理:如果key不存在,则创建并返回锁;如果key存在则抛异常(developer负责控制命名规则)

锁的lock操作:

  • 锁空闲,则current thread成功上锁,返回TRUE
  • 锁被占用,则current thread抓锁失败(即使锁的当前所有者是自己),返回FALSE

锁的unlock操作:

  • 锁的拥有者是current thread,解锁成功
  • 锁的拥有者不是current thread,抛异常

加锁场景:

参见加锁场景分析

1.3.2 空值
  • 索引构建时,property为空怎么处理?参考mysql数据库实现,用0、特殊值或者空串代替空值

2. 索引删除

删除某个indexLabel对应的索引信息和indexLabel本身,场景如下:

  1. 用户删除特定indexLabel
  2. 删除vertex label或者edge label时,需要删除建立在其上的index
  3. 删除vertexLabel或者edgeLabel的某个建有索引的property,需要先删除property相关的索引

先删除index表中的具体索引数据,再从vertex label或者edge label的index_names中删除对应的indexName,之后删除indexLabel表中的元数据

2.1 设计要点

  • 从功能上看,Cassandra不支持不包含第一列的where语句,对于secondary index需要先查询出所有符合要求的index,再一条一条删除;searchIndex第一列为index_label_name,则可以根据通过___delete from search_indexes where index_label_name = yyy___批量删除
// delete index data from secondary index table
DELETE FROM secondary_indexes WHERE PROPERTY_VALUES='Beijing' AND INDEX_LABEL_NAME='personByCity';

// delete index data from search index table
DELETE FROM search_indexes WHERE INDEX_LABEL_NAME='personByAge';
  • 构造一个新的backendEntry,propValues和elementIDs都为空,表示___delete from table where indexLabelName = xxx___语句,传递到store,由store根据是secondary还是search选择不同的处理方式