В базе данных есть 10 000 записей, у каждой записи своя позиция 1, 2, 3… и так до 10 000. Все они выводятся на страницу и пользователь предоставляется возможность переместить эту запись на какую угодно позицию. Пример: Я беру запись под номером 10 и перемещаю её на место записи 50. При этом в базе данных должно произойти смещение записей (10 запись становится 50, а 50 становится 51, 52 становится 53 и т.д.). Все бы хорошо, но я не считаю это нормальным изменять нумерацию десяти тысяч позиций при каждом перемещении. Что можете посоветовать?
Добавьте поле ранг, которое будет отвечать за позицию. Позиция должна задаваться с определёнными промежутками. Например, первая запись — ранг = 100, вторая запись — ранг равен 200, и т.д.
Когда вы переносите запись Вам достаточно изменить ранг на середину промежутка между соответствующими записями. Например, первую запись вы переместили на 50 место, т.е. между 49 и бывшим 50, тогда Вам достаточно установить ранг для новой записи 4950. Остальные записи трогать не надо.
Промежуток между записями выбирается в зависимости от частоты изменений + периодически необходимо производить выравнивание рангов.
Соответсвенно выбирайте разницу между рангами в зависимости от частоты перемещений, и через промежутки времени (раз в день, неделю, месяц — выбираетсяя также в зависимости от частоты перемещений объектов) выравнивайте ранги (выставляйте всем снова 100 200 300...)
Как вариант — организовать записи в таблице как связанный список (однонаправленный, либо двунаправленный, в зависимости от задачи). В таком случае, при перемещении той или иной записи будут меняться ссылки лишь в записях, которые были до и после перемещаемой и в тех между которыми встанет перемещаемая запись.
Это точно можно назвать предварительной оптимизацией :)
Почему вы считаете что это ненормально? Сдвинуть нумерацию для всех последующих строк — один ненапряжный запрос.
Сколько нагрузки дадут все эти методы «оптимизации» по сравнению со сдвигом?
Как часто происходит перенумерация по сравнению с обычной выборкой? Может не стоит вообще заморачиваться с тем что происходит крайне редко?
Насколько усложнит и замедлит частые операции выборки дополнительные методы «оптимизации» редкой и ненагружаемой операции?
Если у вас не бывает перетасовки всего списка, а перемещение лишь одной записи (при том что это происходит не особенно часто), я бы порекомендовал вам выполнить сортировку в два запроса
-- к примеру новый ранг = 10
-- id сдвигаемой записи 100500
UPDATE `my_table` SET `ordering` = `ordering` + 1 WHERE `ordering`>=10;
UPDATE `my_table` SET `ordering` = 10 WHERE `id`=100500;
Дополнительно отмечу, что этот способ будет неэффективен, когда размер таблицы приблизится к сотни тыс. записей — обновление индекса затратно (речь об `ordering`), а без индекса будет медленный отбор (секция WHERE).
Если записей не так много и обновляются они не очень часто, то этот способ для вас лучший