Search in sources :

Example 1 with PrimaryIndexPrefixScan

use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.

the class SQLPlanner method discoverIndexOperations.

private void discoverIndexOperations(Expression expressionWhere, Table table, String mainTableAlias, SQLRecordPredicate where, TableSpaceManager tableSpaceManager) throws StatementExecutionException {
    SQLRecordKeyFunction keyFunction = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, EqualsTo.class);
    IndexOperation result = null;
    if (keyFunction != null) {
        if (keyFunction.isFullPrimaryKey()) {
            result = new PrimaryIndexSeek(keyFunction);
        } else {
            result = new PrimaryIndexPrefixScan(keyFunction);
        }
    } else {
        SQLRecordKeyFunction rangeMin = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, GreaterThanEquals.class);
        if (rangeMin != null && !rangeMin.isFullPrimaryKey()) {
            rangeMin = null;
        }
        if (rangeMin == null) {
            rangeMin = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, GreaterThan.class);
            if (rangeMin != null && !rangeMin.isFullPrimaryKey()) {
                rangeMin = null;
            }
        }
        SQLRecordKeyFunction rangeMax = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, MinorThanEquals.class);
        if (rangeMax != null && !rangeMax.isFullPrimaryKey()) {
            rangeMax = null;
        }
        if (rangeMax == null) {
            rangeMax = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, MinorThan.class);
            if (rangeMax != null && !rangeMax.isFullPrimaryKey()) {
                rangeMax = null;
            }
        }
        if (rangeMin != null || rangeMax != null) {
            result = new PrimaryIndexRangeScan(table.primaryKey, rangeMin, rangeMax);
        }
    }
    if (result == null) {
        Map<String, AbstractIndexManager> indexes = tableSpaceManager.getIndexesOnTable(table.name);
        if (indexes != null) {
            // TODO: use some kind of statistics, maybe using an index is more expensive than a full table scan
            for (AbstractIndexManager index : indexes.values()) {
                if (!index.isAvailable()) {
                    continue;
                }
                IndexOperation secondaryIndexOperation = findSecondaryIndexOperation(index, expressionWhere, table);
                if (secondaryIndexOperation != null) {
                    result = secondaryIndexOperation;
                    break;
                }
            }
        }
    }
    where.setIndexOperation(result);
    Expression filterPk = findFiltersOnPrimaryKey(table, table.name, expressionWhere);
    where.setPrimaryKeyFilter(filterPk);
}
Also used : MinorThan(net.sf.jsqlparser.expression.operators.relational.MinorThan) IndexOperation(herddb.index.IndexOperation) PrimaryIndexSeek(herddb.index.PrimaryIndexSeek) AbstractIndexManager(herddb.core.AbstractIndexManager) GreaterThan(net.sf.jsqlparser.expression.operators.relational.GreaterThan) Expression(net.sf.jsqlparser.expression.Expression) AlterExpression(net.sf.jsqlparser.statement.alter.AlterExpression) BinaryExpression(net.sf.jsqlparser.expression.BinaryExpression) AndExpression(net.sf.jsqlparser.expression.operators.conditional.AndExpression) SignedExpression(net.sf.jsqlparser.expression.SignedExpression) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) PrimaryIndexPrefixScan(herddb.index.PrimaryIndexPrefixScan) PrimaryIndexRangeScan(herddb.index.PrimaryIndexRangeScan)

Example 2 with PrimaryIndexPrefixScan

use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.

the class CalcitePlanner method scanForIndexAccess.

private IndexOperation scanForIndexAccess(CompiledSQLExpression expressionWhere, Table table, TableSpaceManager tableSpaceManager) {
    SQLRecordKeyFunction keyFunction = findIndexAccess(expressionWhere, table.primaryKey, table, "=", table);
    IndexOperation result = null;
    if (keyFunction != null) {
        if (keyFunction.isFullPrimaryKey()) {
            result = new PrimaryIndexSeek(keyFunction);
        } else {
            result = new PrimaryIndexPrefixScan(keyFunction);
        }
    } else {
        SQLRecordKeyFunction rangeMin = findIndexAccess(expressionWhere, table.primaryKey, table, ">=", table);
        if (rangeMin != null && !rangeMin.isFullPrimaryKey()) {
            rangeMin = null;
        }
        if (rangeMin == null) {
            rangeMin = findIndexAccess(expressionWhere, table.primaryKey, table, ">", table);
            if (rangeMin != null && !rangeMin.isFullPrimaryKey()) {
                rangeMin = null;
            }
        }
        SQLRecordKeyFunction rangeMax = findIndexAccess(expressionWhere, table.primaryKey, table, "<=", table);
        if (rangeMax != null && !rangeMax.isFullPrimaryKey()) {
            rangeMax = null;
        }
        if (rangeMax == null) {
            rangeMax = findIndexAccess(expressionWhere, table.primaryKey, table, "<", table);
            if (rangeMax != null && !rangeMax.isFullPrimaryKey()) {
                rangeMax = null;
            }
        }
        if (rangeMin != null || rangeMax != null) {
            result = new PrimaryIndexRangeScan(table.primaryKey, rangeMin, rangeMax);
        }
    }
    if (result == null) {
        Map<String, AbstractIndexManager> indexes = tableSpaceManager.getIndexesOnTable(table.name);
        if (indexes != null) {
            // TODO: use some kind of statistics, maybe using an index is more expensive than a full table scan
            for (AbstractIndexManager index : indexes.values()) {
                if (!index.isAvailable()) {
                    continue;
                }
                IndexOperation secondaryIndexOperation = findSecondaryIndexOperation(index, expressionWhere, table);
                if (secondaryIndexOperation != null) {
                    result = secondaryIndexOperation;
                    break;
                }
            }
        }
    }
    return result;
}
Also used : IndexOperation(herddb.index.IndexOperation) PrimaryIndexSeek(herddb.index.PrimaryIndexSeek) AbstractIndexManager(herddb.core.AbstractIndexManager) PrimaryIndexPrefixScan(herddb.index.PrimaryIndexPrefixScan) PrimaryIndexRangeScan(herddb.index.PrimaryIndexRangeScan)

Example 3 with PrimaryIndexPrefixScan

use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.

the class SimpleIndexAccessTest method multipleColumnPrimaryKeyPrefixScanWithAliasTest.

@Test
public void multipleColumnPrimaryKeyPrefixScanWithAliasTest() throws Exception {
    String nodeId = "localhost";
    try (DBManager manager = new DBManager("localhost", new MemoryMetadataStorageManager(), new MemoryDataStorageManager(), new MemoryCommitLogManager(), null, null)) {
        manager.start();
        CreateTableSpaceStatement st1 = new CreateTableSpaceStatement("tblspace1", Collections.singleton(nodeId), nodeId, 1, 0, 0);
        manager.executeStatement(st1, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        manager.waitForTablespace("tblspace1", 10000);
        execute(manager, "CREATE TABLE tblspace1.q1_HISTORY (\n" + "  MSG_ID           BIGINT        NOT NULL,\n" + "  SID              TINYINT       NOT NULL,  \n" + "  STATUS           INT           NOT NULL,\n" + "  TIMESTAMP        TIMESTAMP NOT NULL,\n" + "  STATUSLINE       VARCHAR(2000) NULL,\n" + "  IDBOUNCECATEGORY SMALLINT      NULL,\n" + "  PRIMARY KEY  (MSG_ID, SID)\n" + ") ;", Collections.emptyList());
        assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(1,1,1)", Collections.emptyList()).getUpdateCount());
        assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(1,2,1)", Collections.emptyList()).getUpdateCount());
        assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(1,3,1)", Collections.emptyList()).getUpdateCount());
        assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(2,1,1)", Collections.emptyList()).getUpdateCount());
        assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(2,2,1)", Collections.emptyList()).getUpdateCount());
        {
            TranslatedQuery translate = manager.getPlanner().translate(TableSpace.DEFAULT, "" + "SELECT H.SID, H.STATUS, H.`TIMESTAMP`, H.STATUSLINE, H.IDBOUNCECATEGORY " + "FROM tblspace1.q1_HISTORY AS H " + "WHERE H.MSG_ID=?", Arrays.asList(1), true, true, false, -1);
            ScanStatement scan = translate.plan.mainStatement.unwrap(ScanStatement.class);
            assertTrue(scan.getPredicate().getIndexOperation() instanceof PrimaryIndexPrefixScan);
            try (DataScanner scan1 = manager.scan(scan, translate.context, TransactionContext.NO_TRANSACTION)) {
                assertEquals(3, scan1.consume().size());
            }
        }
    }
}
Also used : CreateTableSpaceStatement(herddb.model.commands.CreateTableSpaceStatement) TranslatedQuery(herddb.sql.TranslatedQuery) DataScanner(herddb.model.DataScanner) MemoryDataStorageManager(herddb.mem.MemoryDataStorageManager) MemoryCommitLogManager(herddb.mem.MemoryCommitLogManager) PrimaryIndexPrefixScan(herddb.index.PrimaryIndexPrefixScan) MemoryMetadataStorageManager(herddb.mem.MemoryMetadataStorageManager) ScanStatement(herddb.model.commands.ScanStatement) Test(org.junit.Test)

Example 4 with PrimaryIndexPrefixScan

use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.

the class BLinkKeyToPageIndex method scanner.

@Override
public Stream<Entry<Bytes, Long>> scanner(IndexOperation operation, StatementEvaluationContext context, TableContext tableContext, AbstractIndexManager index) throws DataStorageManagerException, StatementExecutionException {
    if (operation instanceof PrimaryIndexSeek) {
        PrimaryIndexSeek seek = (PrimaryIndexSeek) operation;
        byte[] seekValue = seek.value.computeNewValue(null, context, tableContext);
        if (seekValue == null) {
            return Stream.empty();
        }
        Bytes key = Bytes.from_array(seekValue);
        Long pageId = getTree().search(key);
        if (pageId == null) {
            return Stream.empty();
        }
        return Stream.of(new AbstractMap.SimpleImmutableEntry<>(key, pageId));
    }
    if (operation instanceof PrimaryIndexPrefixScan) {
        PrimaryIndexPrefixScan scan = (PrimaryIndexPrefixScan) operation;
        // SQLRecordKeyFunction value = sis.value;
        byte[] refvalue = scan.value.computeNewValue(null, context, tableContext);
        Bytes firstKey = Bytes.from_array(refvalue);
        Bytes lastKey = firstKey.next();
        return getTree().scan(firstKey, lastKey);
    }
    // every predicate (WHEREs...) will always be evaluated anyway on every record, in order to guarantee correctness
    if (index != null) {
        return index.recordSetScanner(operation, context, tableContext, this);
    }
    if (operation == null) {
        Stream<Map.Entry<Bytes, Long>> baseStream = getTree().scan(null, null);
        return baseStream;
    } else if (operation instanceof PrimaryIndexRangeScan) {
        Bytes refminvalue;
        PrimaryIndexRangeScan sis = (PrimaryIndexRangeScan) operation;
        SQLRecordKeyFunction minKey = sis.minValue;
        if (minKey != null) {
            refminvalue = Bytes.from_array(minKey.computeNewValue(null, context, tableContext));
        } else {
            refminvalue = null;
        }
        Bytes refmaxvalue;
        SQLRecordKeyFunction maxKey = sis.maxValue;
        if (maxKey != null) {
            refmaxvalue = Bytes.from_array(maxKey.computeNewValue(null, context, tableContext));
        } else {
            refmaxvalue = null;
        }
        return getTree().scan(refminvalue, refmaxvalue, refmaxvalue != null);
    }
    throw new DataStorageManagerException("operation " + operation + " not implemented on " + this.getClass());
}
Also used : AbstractMap(java.util.AbstractMap) PrimaryIndexSeek(herddb.index.PrimaryIndexSeek) Bytes(herddb.utils.Bytes) Entry(java.util.Map.Entry) DataStorageManagerException(herddb.storage.DataStorageManagerException) AtomicLong(java.util.concurrent.atomic.AtomicLong) PrimaryIndexPrefixScan(herddb.index.PrimaryIndexPrefixScan) PrimaryIndexRangeScan(herddb.index.PrimaryIndexRangeScan) SQLRecordKeyFunction(herddb.sql.SQLRecordKeyFunction)

Example 5 with PrimaryIndexPrefixScan

use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.

the class SimpleIndexAccessTest method multipleColumnPrimaryKeyPrefixScanTest.

@Test
public void multipleColumnPrimaryKeyPrefixScanTest() throws Exception {
    String nodeId = "localhost";
    try (DBManager manager = new DBManager("localhost", new MemoryMetadataStorageManager(), new MemoryDataStorageManager(), new MemoryCommitLogManager(), null, null)) {
        manager.start();
        CreateTableSpaceStatement st1 = new CreateTableSpaceStatement("tblspace1", Collections.singleton(nodeId), nodeId, 1, 0, 0);
        manager.executeStatement(st1, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        manager.waitForTablespace("tblspace1", 10000);
        execute(manager, "CREATE TABLE tblspace1.tsql (k1 string," + "n1 int," + "s1 string, " + "primary key (k1,n1)" + ")", Collections.emptyList());
        assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.tsql(k1,n1) values(?,?)", Arrays.asList("mykey", Integer.valueOf(1234))).getUpdateCount());
        assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.tsql(k1,n1) values(?,?)", Arrays.asList("mykey", Integer.valueOf(1235))).getUpdateCount());
        {
            TranslatedQuery translate = manager.getPlanner().translate(TableSpace.DEFAULT, "SELECT k1 as theKey,'one' as theStringConstant,3  LongConstant FROM tblspace1.tsql where k1 = ?", Arrays.asList("mykey"), true, true, false, -1);
            ScanStatement scan = translate.plan.mainStatement.unwrap(ScanStatement.class);
            assertTrue(scan.getPredicate().getIndexOperation() instanceof PrimaryIndexPrefixScan);
            try (DataScanner scan1 = manager.scan(scan, translate.context, TransactionContext.NO_TRANSACTION)) {
                assertEquals(2, scan1.consume().size());
            }
        }
        {
            TranslatedQuery translate = manager.getPlanner().translate(TableSpace.DEFAULT, "SELECT k1 as theKey,'one' as theStringConstant,3  LongConstant FROM tblspace1.tsql where k1 = ? and n1 <> 1235", Arrays.asList("mykey"), true, true, false, -1);
            ScanStatement scan = translate.plan.mainStatement.unwrap(ScanStatement.class);
            assertTrue(scan.getPredicate().getIndexOperation() instanceof PrimaryIndexPrefixScan);
            try (DataScanner scan1 = manager.scan(scan, translate.context, TransactionContext.NO_TRANSACTION)) {
                assertEquals(1, scan1.consume().size());
            }
        }
        {
            TranslatedQuery translate = manager.getPlanner().translate(TableSpace.DEFAULT, "SELECT k1 as theKey,'one' as theStringConstant,3  LongConstant FROM tblspace1.tsql where k1 = ? and n1 = 1235", Arrays.asList("mykey"), true, true, false, -1);
            ScanStatement scan = translate.plan.mainStatement.unwrap(ScanStatement.class);
            assertTrue(scan.getPredicate().getIndexOperation() instanceof PrimaryIndexSeek);
            try (DataScanner scan1 = manager.scan(scan, translate.context, TransactionContext.NO_TRANSACTION)) {
                assertEquals(1, scan1.consume().size());
            }
        }
    }
}
Also used : CreateTableSpaceStatement(herddb.model.commands.CreateTableSpaceStatement) PrimaryIndexSeek(herddb.index.PrimaryIndexSeek) TranslatedQuery(herddb.sql.TranslatedQuery) DataScanner(herddb.model.DataScanner) MemoryDataStorageManager(herddb.mem.MemoryDataStorageManager) MemoryCommitLogManager(herddb.mem.MemoryCommitLogManager) PrimaryIndexPrefixScan(herddb.index.PrimaryIndexPrefixScan) MemoryMetadataStorageManager(herddb.mem.MemoryMetadataStorageManager) ScanStatement(herddb.model.commands.ScanStatement) Test(org.junit.Test)

Aggregations

PrimaryIndexPrefixScan (herddb.index.PrimaryIndexPrefixScan)5 PrimaryIndexSeek (herddb.index.PrimaryIndexSeek)4 PrimaryIndexRangeScan (herddb.index.PrimaryIndexRangeScan)3 AbstractIndexManager (herddb.core.AbstractIndexManager)2 IndexOperation (herddb.index.IndexOperation)2 MemoryCommitLogManager (herddb.mem.MemoryCommitLogManager)2 MemoryDataStorageManager (herddb.mem.MemoryDataStorageManager)2 MemoryMetadataStorageManager (herddb.mem.MemoryMetadataStorageManager)2 DataScanner (herddb.model.DataScanner)2 CreateTableSpaceStatement (herddb.model.commands.CreateTableSpaceStatement)2 ScanStatement (herddb.model.commands.ScanStatement)2 TranslatedQuery (herddb.sql.TranslatedQuery)2 Test (org.junit.Test)2 SQLRecordKeyFunction (herddb.sql.SQLRecordKeyFunction)1 CompiledSQLExpression (herddb.sql.expressions.CompiledSQLExpression)1 DataStorageManagerException (herddb.storage.DataStorageManagerException)1 Bytes (herddb.utils.Bytes)1 AbstractMap (java.util.AbstractMap)1 Entry (java.util.Map.Entry)1 AtomicLong (java.util.concurrent.atomic.AtomicLong)1