Порядок записей в таблице - PullRequest
0 голосов
/ 06 июня 2009

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

Таблица изображений выглядит следующим образом:

entry_id   |   entry_data
-------------------------
1          | data1
2          | data2
...        | ...
n          | datan

entry_id - это, конечно, первичный ключ с опцией AI, поэтому все записи имеют уникальный идентификатор. Сейчас. Я хочу заказать эти данные. Скажем, я хочу, чтобы entry_id = 2 был первым, не меняя его entry_id. Тогда таблице нужен еще один столбец для хранения номера заказа. Я пробовал 2 подхода.

  1. entry_order_no : это в основном сохранит номер заказа элементов. Любой новый предмет всегда будет добавлен в конец.

  2. left_id + right_id : этот подход используется phpBB. Не уверен, почему для этого требуется right_id?

Кажется, я предпочитаю 1-й подход, но как вы сортируете данные позже. Предположим, я хочу, чтобы вновь добавленный элемент переместился с последней позиции, скажем, на 2-ю. То, как я это делал, я использовал индексированные таблицы, где индекс был порядковым номером. Каждый индекс содержал ассоциативный массив, который имел entry_id. Таким образом, я «просто» сделал цикл foreach с ОБНОВЛЕНИЕМ для всех записей со 2-го места вниз. Это может работать для нескольких строк. Может быть, даже десятки. Но что, когда у вас есть сотни? Это кажется крайне неэффективным. Второй кажется немного лучше. Но что-то все еще говорит мне, что есть лучший подход.

Пожалуйста, предложите.

Ответы [ 6 ]

2 голосов
/ 06 июня 2009

Я не уверен в истинной природе того, почему вы пытаетесь это сделать, поэтому сложно сказать, но что касается вашего неэффективного цикла foreach, прекратите использовать итерационные методы на множествах - используйте операции над множествами, они быстрее и именно для чего предназначена БД. так что вместо ...

for row in db>2
    entryorderno += 1

сделай это ...

UPDATE Table
SET entryorderno = entryorderno + 1
WHERE entryorderno > 2

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

1 голос
/ 06 июня 2009

phpBB использует более разумный подход: left_id и right_id соответствуют узлам дерева как часть вложенного набора . Вероятно, это тот путь, по которому вы хотите пойти, если производительность будет проблемой (поскольку вы, кажется, беспокоитесь об этом). Вот очень подробное описание реализации вложенных множеств .

Но учтите, что базы данных обычно предназначены для неупорядоченных данных. Чтобы получить отсортированные данные, вы обычно извлекаете все интересующие вас строки, а затем выполняете постобработку - например, с предложением ORDER BY или сортируете результаты после их возвращения.

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

0 голосов
/ 06 июня 2009

Как насчет хранения простого столбца порядка сортировки и использования триггеров и хранимых функций в вашей базе данных?

Триггер сработает при каждом обновлении столбца order и увеличит все ордера, превышающие новый ордер, на 1. Сотни или тысячи записей не должны быть проблемой для любой приличной базы данных, особенно когда обработка выполняется внутри БД (я бы не рекомендовал бы делать это из своего приложения), хотя, как только вы попадете в десятки миллионов, обновление этого количества строк будет проблематичным.

Зависит от размера ваших данных.

0 голосов
/ 06 июня 2009

Если вам требуется искусственный порядок (порядок, который вы не можете создать динамически путем сортировки по некоторым столбцам), вы должны добавить столбец Position. Когда вы затем переупорядочиваете две строки, вы должны изменить все строки между ними, если вы используете плотное кодирование.

У вас есть возможность использовать код потери - например, первая строка получает позицию 100, вторая 200, третья 300 и так далее. Это увеличит сложность вашей логики, но позволит вам выполнить ряд операций переупорядочения без необходимости изменять более одной строки.

0 голосов
/ 06 июня 2009

интересный вопрос. Left_id / right_id, вероятно, является реализацией подхода с использованием вложенных множеств для хранения иерархических (в отличие от последовательных) данных. См. Деревья в SQL .

.

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

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

0 голосов
/ 06 июня 2009

Назад, когда мы программировали в первобытном Basic, мы пронумеровали строки «10, 20, 30, ...», поэтому, если нам когда-нибудь понадобилось вставить строку между существующими, мы могли бы просто пронумеровать ее, скажем, 25, без нумерации всех остальных , Вы могли бы использовать подобный прием для своего «порядка входа», если его единственная цель состоит в том, чтобы сохранить порядок строк и, тем не менее, позволить изменить этот порядок с минимумом суеты, не перенумеровывая все (внутреннему mysql придется обновить индекс по этот столбец, но это все же быстрее, чем делать это самостоятельно, скорее всего, чем нет - попробуйте некоторые тесты на вашей установке, чтобы подтвердить это). Используйте BIGINT и большое начальное приращение, скажем, 1024, и у вас должно быть достаточно для нескольких переупорядочений, прежде чем вам потребуется перестроить этот столбец.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...