Classificar-mesclar junção - Sort-merge join

A junção sort-merge (também conhecida como junção de mesclagem) é um algoritmo de junção e é usada na implementação de um sistema de gerenciamento de banco de dados relacional .

O problema básico de um algoritmo de junção é encontrar, para cada valor distinto do atributo de junção, o conjunto de tuplas em cada relação que exibe esse valor. A ideia principal do algoritmo de ordenação e mesclagem é primeiro ordenar as relações pelo atributo de junção, de forma que varreduras lineares intercaladas encontrem esses conjuntos ao mesmo tempo.

Na prática, a parte mais cara de realizar uma junção de classificação e mesclagem é organizar para que ambas as entradas para o algoritmo sejam apresentadas em ordem classificada. Isso pode ser obtido por meio de uma operação de classificação explícita (geralmente uma classificação externa ) ou aproveitando uma ordenação pré-existente em uma ou ambas as relações de junção. A última condição, chamada de ordem interessante, pode ocorrer porque uma entrada para a junção pode ser produzida por uma varredura de índice de um índice baseado em árvore, outra junção de mesclagem ou algum outro operador de plano que produza a saída classificada em uma chave apropriada. Ordens interessantes não precisam ser fortuitas: o otimizador pode buscar essa possibilidade e escolher um plano que não seja o ideal para uma operação anterior específica, se produzir uma ordem interessante que um ou mais nós downstream possam explorar.

Digamos que temos duas relações e e . cabe na memória de páginas e cabe na memória de páginas. Portanto, no pior caso , a junção sort-merge será executada em I / Os. No caso em que e não são ordenados a pior custo de tempo caso irá conter termos adicionais de triagem tempo: que é igual (como linearithmic termos superam os termos lineares, consulte Big O notação - Ordens de funções comuns ).

Pseudo-código

Para simplificar, o algoritmo é descrito no caso de uma junção interna de duas relações em um único atributo. A generalização para outros tipos de junção, mais relações e mais chaves é direta.

function sortMerge(relation left, relation right, attribute a)
    var relation output
    var list left_sorted := sort(left, a) // Relation left sorted on attribute a
    var list right_sorted := sort(right, a)
    var attribute left_key, right_key
    var set left_subset, right_subset // These sets discarded except where join predicate is satisfied
    advance(left_subset, left_sorted, left_key, a)
    advance(right_subset, right_sorted, right_key, a)
    while not empty(left_subset) and not empty(right_subset)
        if left_key = right_key // Join predicate satisfied
            add cartesian product of left_subset and right_subset to output
            advance(left_subset, left_sorted, left_key, a)
            advance(right_subset, right_sorted, right_key, a)
        else if left_key < right_key
            advance(left_subset, left_sorted, left_key, a)
        else // left_key > right_key
            advance(right_subset, right_sorted, right_key, a)
    return output
// Remove tuples from sorted to subset until the sorted[1].a value changes
function advance(subset out, sorted inout, key out, a in)
    key := sorted[1].a
    subset := emptySet
    while not empty(sorted) and sorted[1].a = key
        insert sorted[1] into subset
        remove sorted[1]

Implementação simples de C #

Observe que esta implementação assume que os atributos de junção são únicos, ou seja, não há necessidade de gerar múltiplas tuplas para um determinado valor da chave.

public class MergeJoin
{
    // Assume that left and right are already sorted
    public static Relation Merge(Relation left, Relation right)
    {
        Relation output = new Relation();
        while (!left.IsPastEnd() && !right.IsPastEnd())
        {
            if (left.Key == right.Key)
            {
                output.Add(left.Key);
                left.Advance();
                right.Advance();
            }
            else if (left.Key < right.Key)
                left.Advance();
            else // if (left.Key > right.Key)
                right.Advance();
        }
        return output;
    }
}
 
public class Relation
{
    private List<int> list;
    public const int ENDPOS = -1;

    public int position = 0;
    public int Position
    {
        get { return position; }
    }

    public int Key
    {
        get { return list[position]; }
    }

    public bool Advance()
    {
        if (position == list.Count - 1 || position == ENDPOS)
        {
            position = ENDPOS;
            return false;
        }
        position++;
        return true;
    }

    public void Add(int key)
    {
        list.Add(key);
    }

    public bool IsPastEnd()
    {
        return position == ENDPOS;
    }

    public void Print()
    {
        foreach (int key in list)
            Console.WriteLine(key);
    }

    public Relation(List<int> list)
    {
        this.list = list;
    }

    public Relation()
    {
        this.list = new List<int>();
    }
}

Veja também

links externos

Implementações C # de vários algoritmos de junção