nosql中的index

来源:互联网 发布:算法 第四版 编辑:程序博客网 时间:2024/06/10 03:28

cassandra中的SecondaryIndex的应用场景主要在于没有带着rowkey的查询。虽然带着rowkey的条件进行检索式cassandra这种非关系型数据库的主流检索,但是使用nosql DB的时候,往往一些统计功能,或者公共的功能,(例如关注度最高的微博,操作次数最多的操作等等)这些不需要和用户绑定,但是又是很多应用不可少的检索功能。并且在cassandra这种海量级的nosql DB中,如果没有Secondary Index这种功能提升没有带rowkey的查询性能的功能,那么就会丧失很多机会,让很多系统发展以后,都没有办法扩展自己的能力。

1、SecondaryIndex的结构

Secondary Index和所有的数据库的index一样是一个牺牲容量,换取某种查询性能的功能。系统会新建一个index表,来存放便于检索的数据,从而加快检索。而cassandra数据库的检索最成熟的条件,就是rowkey。所以Secondary index就是一个以index字段为rowkey,以数据表中的rowkey作为Column的StandCF。

在1.2版本的cassandra中实现的KeyIndex和CompositeIndex都是继承AbstractSimplePerColumnSecondaryIndex简单单列index的实现类。

public void init()    {        assert baseCfs != null && columnDefs != null && columnDefs.size() == 1;        ColumnDefinition columnDef = columnDefs.iterator().next();        init(columnDef);        AbstractType indexComparator = SecondaryIndex.getIndexComparator(baseCfs.metadata, columnDef);        CFMetaData indexedCfMetadata = CFMetaData.newIndexMetadata(baseCfs.metadata, columnDef, indexComparator);        indexCfs = ColumnFamilyStore.createColumnFamilyStore(baseCfs.table,                                                             indexedCfMetadata.cfName,                                                             new LocalPartitioner(columnDef.getValidator()),                                                             indexedCfMetadata);        // enable and initialize row cache based on parent's setting and indexed column's cardinality        CFMetaData.Caching baseCaching = baseCfs.metadata.getCaching();        if (baseCaching == CFMetaData.Caching.ALL || baseCaching == CFMetaData.Caching.ROWS_ONLY)        {            /*             * # of index CF's key = cardinality of indexed column.             * if # of keys stored in index CF is more than average column counts (means tall table),             * then consider it as high cardinality.             */            double estimatedKeys = indexCfs.estimateKeys();            double averageColumnCount = indexCfs.getMeanColumns();            if (averageColumnCount > 0 && estimatedKeys / averageColumnCount > 1)            {                logger.debug("turning row cache on for " + indexCfs.getColumnFamilyName());                indexCfs.metadata.caching(baseCaching);                indexCfs.initRowCache();            }        }    }

2、SecondaryIndex表的属性

SecondaryIndex的CF的属性有:

属性名属性值keyspaceName源CF的keyspaceNameCFTypeStandard CFRowkey的类型index字段的类型读修复概率0GC清理时间0keycache开启配置如果源CF开启则开启RowCache开启配置否compact策略与源CF一致compress策略与源CF一致

public static CFMetaData newIndexMetadata(CFMetaData parent, ColumnDefinition info, AbstractType<?> columnComparator)    {        // Depends on parent's cache setting, turn on its index CF's cache.        // Here, only key cache is enabled, but later (in KeysIndex) row cache will be turned on depending on cardinality.        Caching indexCaching = parent.getCaching() == Caching.ALL || parent.getCaching() == Caching.KEYS_ONLY                             ? Caching.KEYS_ONLY                             : Caching.NONE;        return new CFMetaData(parent.ksName, parent.indexColumnFamilyName(info), ColumnFamilyType.Standard, columnComparator, null)                             .keyValidator(info.getValidator())                             .readRepairChance(0.0)                             .dcLocalReadRepairChance(0.0)                             .gcGraceSeconds(0)                             .caching(indexCaching)                             .compactionStrategyClass(parent.compactionStrategyClass)                             .compactionStrategyOptions(parent.compactionStrategyOptions)                             .reloadSecondaryIndexMetadata(parent);    }


3、SecondaryIndex创建的条件

在普通的CF创建的时候,如果Column定义的时候,indexType属性可以为KEYS(即为KeyIndex),COMPOSITES(即为CompositeIndex),CUSTOM(即为用户自己二次开发的index功能)。

在1.2版本的cassandra中,目前只支持KeyIndex,主要是针对StandCF的普通Column的和CompositeIndex主要是针对CompositeCF的普通Column。

/**     * Drops and adds new indexes associated with the underlying CF     */    public void reload()    {        // figure out what needs to be added and dropped.        // future: if/when we have modifiable settings for secondary indexes,        // they'll need to be handled here.        Collection<ByteBuffer> indexedColumnNames = indexesByColumn.keySet();        for (ByteBuffer indexedColumn : indexedColumnNames)        {            ColumnDefinition def = baseCfs.metadata.getColumn_metadata().get(indexedColumn);            if (def == null || def.getIndexType() == null)                removeIndexedColumn(indexedColumn);        }        for (ColumnDefinition cdef : baseCfs.metadata.getColumn_metadata().values())            if (cdef.getIndexType() != null && !indexedColumnNames.contains(cdef.name))                addIndexedColumn(cdef);        Set<SecondaryIndex> reloadedIndexes = Collections.newSetFromMap(new IdentityHashMap<SecondaryIndex, Boolean>());        for (SecondaryIndex index : indexesByColumn.values())        {            if (reloadedIndexes.add(index))                index.reload();        }    }

4、SecondaryIndex的应用




5、SecondaryIndex与源数据表的关系

Secondary IndexCF都是每个节点自己的本地表,没有副本,所以当数据迁移的时候,需要重新生成对应的index数据。

(1)重启的时候,需要在加载数据表的时候,加载出对应的indexCF结构。这样就根据indexInfo系统表中有没有对应的indexCF的记录,判断indexCF是否需要生成index数据,如果IndexInfo系统表有对应的indexCF数据,则不需要重新生成indexCF的数据,如果没有,则需要重新生成。

问题:如果indexCF在生成对应的数据的时候,此时进行的index条件的查询,由于index数据还没有生成完全导致极大可能差不多数据。




原创粉丝点击