nosqlのindex

6032 ワード

cassandraのSecondaryIndexのアプリケーションシーンは、主にrowkey付きクエリーがないことにあります.検索式cassandraのような非関係型データベースの主流検索をrowkeyの条件で行うが,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のkeyspaceName
CFType
Standard CF
Rowkeyのタイプ
indexフィールドのタイプ
リードリペア確率
0
GC清掃時間
0
keycacheオープン構成
ソース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)、COMPOSIES(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 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 reloadedIndexes = Collections.newSetFromMap(new IdentityHashMap());
        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データが生成されていないため、完全にデータが差が少ない可能性があります.