Jump to content

Соединение сортировки-слияния

Соединение сортировки -слияния (также известное как соединение слиянием) представляет собой алгоритм соединения и используется при реализации реляционными системы управления базами данных .

Основная проблема алгоритма соединения состоит в том, чтобы найти для каждого отдельного значения атрибута соединения набор кортежей в каждом отношении, которые отображают это значение. Основная идея алгоритма сортировки-слияния состоит в том, чтобы сначала отсортировать отношения по атрибуту соединения, чтобы чередующиеся линейные сканирования встречали эти наборы одновременно.

На практике самая затратная часть выполнения соединения сортировки-слияния — это организация представления обоих входных данных алгоритма в отсортированном порядке. Этого можно достичь с помощью явной операции сортировки (часто внешней сортировки ) или использования уже существующего порядка в одном или обоих отношениях соединения. [1] Последнее условие, называемое интересным порядком, может возникнуть, поскольку входные данные для соединения могут быть получены в результате сканирования индекса на основе дерева, другого соединения слиянием или какого-либо другого оператора плана, который производит выходные данные, отсортированные по соответствующему ключу. Интересные заказы не обязательно должны быть случайными: оптимизатор может искать эту возможность и выбирать план, который неоптимален для конкретной предыдущей операции, если он дает интересный порядок, который могут использовать один или несколько нижестоящих узлов.

Сложность

[ редактировать ]

Позволять и быть отношениями, где . вписывается память страниц и вписывается Память страниц. В худшем случае соединение сортировки-слияния. будет выполнено Операции ввода-вывода. В случае, если и не заказываются, в худшем случае стоимость времени будет содержать дополнительные условия сортировки времени: , что равно (поскольку линейные члены перевешивают линейные, см. Обозначение Big O – Порядки общих функций ).

Псевдокод

[ редактировать ]

Для простоты алгоритм описан в случае внутреннего соединения двух отношений left и right . Обобщение на другие типы соединений несложно. Выходные данные алгоритма будут содержать только строки, содержащиеся в левом и правом отношении, а дубликаты образуют декартово произведение .

function Sort-Merge Join(left: Relation, right: Relation, comparator: Comparator) {
    result = new Relation()
    
    // Ensure that at least one element is present
    if (!left.hasNext() || !right.hasNext()) {
        return result
    }
    
    // Sort left and right relation with comparator
    left.sort(comparator)
    right.sort(comparator)
    
    // Start Merge Join algorithm
    leftRow = left.next()
    rightRow = right.next()
    
    outerForeverLoop:
    while (true) {
        while (comparator.compare(leftRow, rightRow) != 0) {
            if (comparator.compare(leftRow, rightRow) < 0) {
                // Left row is less than right row
                if (left.hasNext()) {
                    // Advance to next left row
                    leftRow = left.next()
                } else {
                    break outerForeverLoop
                }
            } else {
                // Left row is greater than right row
                if (right.hasNext()) {
                    // Advance to next right row
                    rightRow  = right.next()
                } else {
                    break outerForeverLoop
                }
            }
        }
        
        // Mark position of left row and keep copy of current left row
        left.mark()
        markedLeftRow = leftRow
        
        while (true) {
            while (comparator.compare(leftRow, rightRow) == 0) {
                // Left row and right row are equal
                // Add rows to result
                result = add(leftRow, rightRow)
                
                // Advance to next left row
                leftRow = left.next()
                
                // Check if left row exists
                if (!leftRow) {
                    // Continue with inner forever loop
                    break
                }
            }
            
            if (right.hasNext()) {
                // Advance to next right row
                rightRow  = right.next()
            } else {
                break outerForeverLoop
            }
            
            if (comparator.compare(markedLeftRow, rightRow) == 0) {
                // Restore left to stored mark
                left.restoreMark()
                leftRow = markedLeftRow
            } else {
                // Check if left row exists
                if (!leftRow) {
                    break outerForeverLoop
                } else {
                    // Continue with outer forever loop
                    break
                }
            }
        }
    }
    
    return result
}

Поскольку логика сравнения не является центральным аспектом этого алгоритма, она скрыта за общим компаратором и также может состоять из нескольких критериев сравнения (например, нескольких столбцов). Функция сравнения должна возвращать значение, если строка меньше (-1) , равна (0) или больше (1) , чем другая строка:

function compare(leftRow: RelationRow, rightRow: RelationRow): number {
	// Return -1 if leftRow is less than rightRow
	// Return 0 if leftRow is equal to rightRow
	// Return 1 if leftRow is greater than rightRow
}

Обратите внимание, что отношение в терминах этого псевдокода поддерживает некоторые основные операции:

interface Relation {
    // Returns true if relation has a next row (otherwise false)
    hasNext(): boolean
    
    // Returns the next row of the relation (if any)
    next(): RelationRow
    
    // Sorts the relation with the given comparator
    sort(comparator: Comparator): void
    
    // Marks the current row index
    mark(): void
    
    // Restores the current row index to the marked row index
    restoreMark(): void
}

Простая реализация C#

[ редактировать ]

Обратите внимание, что эта реализация предполагает, что атрибуты соединения уникальны, т. е. нет необходимости выводить несколько кортежей для данного значения ключа.

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 => position;

    public int Key => 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>();
    }
}

См. также

[ редактировать ]
  1. ^ «Объединения сортировки-слияния» . www.dcs.ed.ac.uk. ​Проверено 2 ноября 2022 г.
[ редактировать ]

Реализации C# различных алгоритмов соединения

Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: a4487c3d96c484ec1cb956a8e2d5e59b__1712289300
URL1:https://arc.ask3.ru/arc/aa/a4/9b/a4487c3d96c484ec1cb956a8e2d5e59b.html
Заголовок, (Title) документа по адресу, URL1:
Sort-merge join - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)