experimento de banco de dados mit 2

documentos de referência

Código

explicar

Índice

  • filtrar, juntar, ordenar por
  • função agregada
  • Inserção e exclusão de tupla
  • Despejo de substituição de página

Experimento 1: juntar e filtrar

predicado :

Três domínios:

  • arquivado: o id do domínio
  • op: operador
  • operando: operando

Implementação da função:

  • filtro()
  • para sequenciar()
    public boolean filter(Tuple t) {
    
    
        // some code goes here
        return t.getField(this.field).compare(op, this.operand);        // 这个compare已经由某一个域给定义好了int和string的比较规则
    }

joinpredict

  • Comparação de campos em duas tuplas para operação de junção

área:

  • campo de duas tuplas
  • operador

função

  • filtro()
  public boolean filter(Tuple t1, Tuple t2) {
    
    
        // some code goes here
        return t1.getField(this.field_a).compare(op, t2.getField(this.field_b));
    }
    

filtro

  • Execute a operação do filtro
  • super.close() e open()
  • buscarNext()
    protected Tuple fetchNext() throws NoSuchElementException,
            TransactionAbortedException, DbException {
    
    
        // some code goes here
        while(child.hasNext()) {
    
    
            Tuple tuple = child.next();
            if (this.p.filter(tuple))                           // 通过过滤器看看是否满足条件
                return tuple;
        }
        return null;
    }

juntar

área:

  • private final JoinPredicate joinPredicate; comparação de tupla dupla
  • private OpIterator child1; iterador de tupla 1
  • private OpIterator filho2; iterador de tupla 2
  • private Tuple t; Tupla temporária, salva a Tupla de child1 usada na última iteração

Isso é usado principalmente para continuar a usar a tupla atual durante a próxima passagem, porque pode haver vários resultados elegíveis, ou seja, um para muitos, então t1 não pode pular diretamente para o próximo e usar um valor temporário para salvar a tupla atual.

função:

  • buscarNext()
protected Tuple fetchNext() throws TransactionAbortedException, DbException {
    
    
    // some code goes here
    // t 的意义就是 笛卡尔积, 一个可能对多个相等
    while (child1.hasNext() || t != null){
    
    
        if(child1.hasNext() && t == null){
    
    
            t = child1.next();
        }
        while(child2.hasNext()){
    
    
            Tuple t2 = child2.next();
            if(joinPredicate.filter(t, t2)){
    
    
                TupleDesc td1 = t.getTupleDesc();
                TupleDesc td2 = t2.getTupleDesc();
                // 合并
                TupleDesc tupleDesc = TupleDesc.merge(td1, td2);
                Tuple newTuple = new Tuple(tupleDesc);
                // 设置路径, 暂时不先设置
                // newTuple.setRecordId(t.getRecordId());
                int i = 0;
                for (; i < td1.numFields(); i++) {
    
    
                    newTuple.setField(i, t.getField(i));
                }
                for (int j = 0; j < td2.numFields(); j++) {
    
    
                    newTuple.setField(i + j, t2.getField(j));
                }
                // 遍历完,t2重头,t走向下一个
                if(!child2.hasNext()){
    
    
                    child2.rewind();
                    t = null;
                }
                return newTuple;
            }
        }
        // 重置 child2
        child2.rewind();
        t = null;
    }
    return null;
}

Experimento 2: Agregados

Agregador

área

  • filho: iterador de tabela

  • afield: o id do domínio que precisa ser agregado

  • gfield: o id do campo que precisa ser agrupado

  • gfieldType: O tipo de campo que precisa ser agrupado, pois não há informação na tabela, só pode ser passado pela classe pai.

  • AggHandler: Um manipulador personalizado usado para implementar diferentes funções de agregação. Cabe ao operador decidir que tipo de função agregada criar.

    • Salve o mapa de resposta {chave: agrupamento, valor: o resultado de cada grupo de funções de agregação}
    • O método handle, um método abstrato, implementa lógica de função agregada específica.

método

  • mergeTotuple: atualize o conjunto de resultados no manipulador por meio de um manipulador personalizado.

  • iterator: Iterator, que converte o conjunto de resultados em forma de tupla. Em seguida, retorna um iterador sobre a lista de tuplas.

    • O cabeçalho da tupla é {groupVal, aggVal}
    • O conteúdo da tupla é o par chave-valor no mapa

o código

    public OpIterator iterator() {
    
    
        // some code goes here
//        throw new
//        UnsupportedOperationException("please implement me for lab2");
        Map<Field, IntField> ans = handler.ans;
        List<Tuple>tuples = new ArrayList<>();
        TupleDesc tupleDesc;                                        // 创建迭代器的时候,需要用到
        if (gfield == NO_GROUPING) {
    
                                  // 如果没有group
            // 创建tuple
            tupleDesc = new TupleDesc(new Type[]{
    
    Type.INT_TYPE}, new String[]{
    
    "aggregateVal"});
            Tuple tuple = new Tuple(tupleDesc);
            // 把查询到的结果放入tuple中
            tuple.setField(0, ans.get(null));
            // 不要忘了把创建的tuple放入到结果集中
            tuples.add(tuple);
        }
        else {
    
                                                         // 如果含有group
            tupleDesc = new TupleDesc(new Type[]{
    
    this.gfieldtype, Type.INT_TYPE}, new String[]{
    
    "groupVal", "aggregateVal"});
            for (Map.Entry<Field, IntField> entry : ans.entrySet()) {
    
    
                Tuple tuple = new Tuple(tupleDesc);
                tuple.setField(0, entry.getKey());
                tuple.setField(1, entry.getValue());
                tuples.add(tuple);
            }
        }
        return new TupleIterator(tupleDesc, tuples);
    }
    public void mergeTupleIntoGroup(Tuple tup) {
    
    
        // some code goes here
        // 获取对应域的值
        IntField afield = (IntField) tup.getField(this.afield);
        Field gfield = this.gfield == NO_GROUPING ? null : tup.getField(this.gfield);
        handler.handle(gfield, afield);
    }
private abstract class AggHandler {
    
    
        private Map<Field, IntField>ans;
        abstract void handle(Field gfield, IntField afield);            // group by不知道什么类型,但是聚集函数得到的结果一定是int
        public AggHandler() {
    
    
            ans = new HashMap<>();
        }
        public Map<Field, IntField> getAns() {
    
    
            return this.ans;
        }
    }
    private class MinHandler extends AggHandler {
    
    
        @Override
        void handle(Field gfield, IntField afield) {
    
    
            int x = afield.getValue();
            Map<Field, IntField>ans = this.getAns();
            if (ans.containsKey(gfield)) {
    
    
                ans.put(gfield, new IntField(Math.min(x, ans.get(gfield).getValue())));
            }
            else ans.put(gfield, new IntField(x));
        }
    }
public IntegerAggregator(int gbfield, Type gbfieldtype, int afield, Op what) {
    
    
        // some code goes here
        this.gfield = gbfield;
        this.afield = afield;
        this.gfieldtype = gbfieldtype;
        this.op = what;
        switch (what) {
    
    
            case MIN:
                this.handler = new MinHandler(); break;
            case AVG:
                this.handler = new AvgHandler(); break;
            case SUM:
                this.handler = new SumHandler(); break;
            case COUNT:
                this.handler = new CountHandler(); break;
            case MAX:
                this.handler = new MaxHandler(); break;
            default:
                throw new IllegalArgumentException("聚合器不支持当前运算符");
        }
    }

Agregados

área:

  • filho: entrada do iterador de tabela
  • afield: id de campo agregado
  • gfield: ID do campo do grupo
  • aop: o id da função agregada
  • agregador: Agregador, um dos acima, cujo tipo é determinado por um campo
  • iterador: o iterador do conjunto de resultados

método:

  • Construtor
  • getTupleDesc(): Retorna um cabeçalho na forma de max(score). Se existe um campo para determinar o número de colunas

código:

  public TupleDesc getTupleDesc() {
    
    
        // some code goes here
//        String afiledName = this.aop.name() + "("  + this.aggregateFieldName() + ")";       // max(id);
//        Type aType = this.child.getTupleDesc().getFieldType(this.afield);
//        if (this.groupFieldName() != null) {
    
    
//            String gfiledName = this.groupFieldName();
//            Type gType = this.child.getTupleDesc().getFieldType(this.gfield);
//            return new TupleDesc(new Type[]{gType, aType},new String[]{gfiledName, afiledName});
//        }
//        else {
    
    
//            return new TupleDesc(new Type[]{aType}, new String[]{afiledName});
//        }
        List<Type>types = new ArrayList<>();
        List<String>names = new ArrayList<>();
        if (groupFieldName() != null) {
    
    
            types.add(this.child.getTupleDesc().getFieldType(this.gfield));
            names.add(groupFieldName());
        }
        types.add(this.child.getTupleDesc().getFieldType(this.afield));
        names.add(this.aop.name() + "(" + aggregateFieldName() + ")");          // 类似于max(id), AVG(score)这种
        if (this.aop.equals(Aggregator.Op.SUM_COUNT)) {
    
                             // 如果有
            types.add(Type.INT_TYPE);
            names.add("COUNT");
        }
        return new TupleDesc(types.toArray(new Type[types.size()]), names.toArray(new String[names.size()]));
    }
    // 这里可以使用工厂模式进行改写
    public Aggregate(OpIterator child, int afield, int gfield, Aggregator.Op aop) {
    
    
        // some code goes here
        this.child = child;
        this.afield = afield;
        this.gfield = gfield;
        this.aop = aop;
        Type gfieldtype;
        if (gfield == NO_GROUPING) gfieldtype = null;
        else gfieldtype = this.child.getTupleDesc().getFieldType(this.gfield);
        if (this.child.getTupleDesc().getFieldType(afield).equals(Type.STRING_TYPE))
            this.aggregator = new StringAggregator(gfield, this.child.getTupleDesc().getFieldType(this.gfield), afield, aop);
        else this.aggregator = new IntegerAggregator(gfield, gfieldtype, afield, aop);
//        desc = this.getTupleDesc();
    }

Experimento 3: HeapPage e HeapFile, bufferpool perfeito

heapPage:

Adicionar ID da transação

inserir e excluir

heapFile

inserir e excluir

buffer pool

  • rubor

  • insertTuple: Essa lógica existe no BufferPoolWriteTest, mas não é obtida do bufferpool, modifique o conteúdo do insert no teste

    • Primeiro, insira se disponível
    • Em segundo lugar, não há nada para inserir, crie uma nova página, insira o arquivo
    • Finalmente, a página é buscada no cache.
      • A lógica das páginas no cache é, se não for lida do arquivo, caso contrário, retornar diretamente
      • Além disso, o get no cache precisa ser reconstruído, a lista duplamente vinculada, o cache está cheio e o final é eliminado.
  • DeleteTuple

  • A lógica no iterador deu errado

Experimento 4: Inserção e exclusão

área

  • ID da transação
  • iterador inserido
  • tabela inserida
  • resultado tupleDesc
  • inserir marca

método

Apenas chame Bufferpool.insert() e delete os métodos diretamente.

Experimento 5: Estratégia de Eliminação

A lista duplamente encadeada implementa LRU.

  1. Coloque a página no topo sempre que usá-la.

Experimento 6: consulta de junção e filtro

  1. Criar um arquivo
  2. Coloque o conteúdo, preste atenção nas quebras de linha
  3. executar arquivo de teste

Experimento 7: uso do analisador de consulta

  1. Criar um arquivo
  2. Execute a conversão do comando, desde que o ant seja compilado através
  3. Finalmente execute o comando e entre na linha de comando
  4. Insira uma consulta e obtenha resultados.

pergunta

  1. Por que o recordId é definido como t1 após a conexão Join?

    1. deve ser definido como uma tabela temporária
    2. mas sem tabela temporária
  2. Por que herdar de Operator em vez de Implement OpIterator

    1. Porque next e hasNext() são métodos duplicados
  3. Por que abrir e fechar precisam de super.open e super.close?

    1. Porque esses dois métodos são substituídos na classe pai. A lógica de julgamento está em hasNext() e next() da classe pai
    2. Portanto, devemos primeiro alterar o estado da classe pai, para passar os dois métodos acima e, em seguida, modificar nosso próprio método.
  4. Qual deve ser o recordId ao criar uma nova tupla?

  5. Qual é o objetivo de definircrianças?

  6. Como sum_count é implementado? Além disso, por que sum_count precisa adicionar uma nova coluna em desc?

    1. Por causa das duas operações, uma nova coluna é adicionada.
  7. Ao inserir e excluir tuplas, o arquivo deve ser gravado imediatamente? Se não, quando o arquivo será gravado?

  8. Por que marcar escrita suja no bufferpool? Não está jogando quando DbFile?

  9. Ao final da eliminação, preciso atualizar o disco? flush e delete são duas operações. Essas duas operações são controladas por camadas superiores. Se você precisar liberar o disco imediatamente, delete(), flush, caso contrário, não precisará.

  10. A lógica no iterador deve ser que não há ninguém nesta página, encontre o primeiro e termine se não houver nenhum.

11. Problemas de codificação

Modifique a cópia na compilação da seguinte maneira

target name="compile" description="Compile code">
        <javac srcdir="${src}/java" destdir="${build.src}" debug="on" deprecation="on" optimize="off" includes="**">
            <!--给编译器指定编码,防止出现:"警告: 编码 GBK 的不可映射字符"-->
            <compilerarg line="-encoding UTF-8 "/>
            <classpath refid="classpath.base" />
        </javac>
        <Compile srcdir="${src}/java" destdir="${build.src}">
            <classpath refid="classpath.base"/>
        </Compile>
    <copy todir="${build}" flatten="true">
        <fileset dir="${src}">
            <include name="bin/*.sh"/>
        </fileset>
    </copy>
    </target>

Resumir

  1. Resumo da depuração: Devido ao problema de no_group_avg encontrado. Execute a depuração de código, atinja os pontos de extremidade no código que você escreveu e esqueça de adicionar tuplas a tuplas.
  2. Ao inserir e excluir, o cache deve ser atualizado no tempo. Em vez de gravar o arquivo imediatamente. Portanto, existem páginas sujas.

Acho que você gosta

Origin blog.csdn.net/fuzekun/article/details/129282283
Recomendado
Clasificación