Итак, практически каждое приложение на основе базы данных должно иметь дело с «неактивными» записями. Либо мягкое удаление, либо отметка чего-то как "игнорируемого". Мне любопытно, есть ли какие-либо радикальные альтернативные мысли об «активном» столбце (или столбце статуса).
Например, если бы у меня был список людей
CREATE TABLE people (
id INTEGER PRIMARY KEY,
name VARCHAR(100),
active BOOLEAN,
...
);
Это означает, что для получения списка активных людей вам нужно использовать
SELECT * FROM people WHERE active=True;
Кто-нибудь предлагает, чтобы неактивные записи были перемещены в отдельную таблицу и где нужно сделать UNION для объединения двух?
Поразительное любопытство ...
Обновлено: Я должен прояснить, я подхожу к этому с точки зрения пуриста. Я понимаю, что архивирование данных может быть необходимо для больших объемов данных, но я исхожу не из этого. Если вы сделаете SELECT * FROM людей, мне будет понятно, что эти записи в некотором смысле "активны"
Спасибо


Активные флаги мы используем довольно часто. Если ваша база данных будет очень большой, я мог бы увидеть смысл в переносе неактивных значений в отдельную таблицу.
Тогда вам потребуется объединение таблиц только тогда, когда кто-то хочет увидеть все записи, активные или неактивные.
Что ж, чтобы гарантировать, что в большинстве ситуаций вы рисуете только активные записи, вы можете создавать представления, которые содержат только активные записи. Так будет намного проще не упустить активную часть.
Активный флаг некрасивый, но простой и хорошо работает.
Вы можете переместить их на другой стол, как вы предложили. Я бы посоветовал посмотреть процент активных / неактивных записей. Если у вас более 20 или 30% неактивных записей, вы можете подумать о перемещении их в другое место. В остальном это не страшно.
В большинстве случаев достаточно двоичного поля, указывающего на удаление. Часто существует механизм очистки, который удаляет эти удаленные записи через определенное время, поэтому вы можете захотеть запустить схему с удаленной меткой времени.
Переход к отдельному столу и возвращение их обратно требует времени. В зависимости от того, сколько записей отключено и как часто вам нужно их возвращать, это может быть или не быть хорошей идеей.
Если в основном они не возвращаются после захоронения и используются только для сводок / отчетов / чего угодно, тогда ваша основная таблица станет меньше, а запросы станут проще и, возможно, быстрее.
Да, хотелось бы. В настоящее время у нас есть столбец «active = 'T / F'» во многих наших таблицах, в основном для отображения «последней» строки. Когда вставляется новая строка, предыдущая T строка помечается буквой F, чтобы сохранить ее для целей аудита.
Теперь мы переходим к подходу с двумя таблицами, когда вставляется новая строка, предыдущая строка перемещается в таблицу истории. Это дает нам лучшую производительность в большинстве случаев - если смотреть на текущие данные.
Стоимость немного больше, чем у старого метода, раньше вам приходилось обновлять и вставлять, теперь вам нужно вставлять и обновлять (т.е. вместо вставки новой строки T вы изменяете существующую строку со всеми новыми данными), поэтому стоимость это просто передача всей строки данных вместо передачи только изменений. Вряд ли это даст какой-то эффект.
Преимущество производительности заключается в том, что индекс вашей основной таблицы значительно меньше, и вы можете лучше оптимизировать свои табличные пространства (они не будут так сильно расти!)
ничего не удаляется, вы перемещаете все записи в таблицу истории и ставите на них флажок. Если вам нужно записать удаление (а не последующее изменение), вам просто нужен новый столбец, чтобы пометить их как удаленные. Однажды кто-нибудь спросит о мертвых данных, и вы сможете ответить на них правильно. Мы не каскадируем связанные записи - если они меняются, то их данные необходимо обновить, но если отношения не изменятся, вам не нужно этого делать - однако наша схема данных была достаточно простой, чтобы позволить это, YMMV.
При этом новая система, с которой я работаю, записывает полностью отдельную таблицу аудита, которая просто записывает все изменения, «автоматически» записывая «столбец X изменен с Y на Z» для всех важных (не всех) изменений данных.
Вы разбиваете таблицу на активный флаг, так что активные записи находятся в одном разделе, а неактивные записи - в другом. Затем вы создаете активное представление для каждой таблицы, которая автоматически содержит активный фильтр. Механизм запросов к базе данных автоматически ограничивает запрос разделом, в котором есть активные записи, что намного быстрее, чем даже использование индекса для этого флага.
Вот пример того, как создать многораздельную таблицу в Oracle. Oracle не имеет логических типов столбцов, поэтому я изменил структуру вашей таблицы для целей Oracle.
CREATE TABLE people
(
id NUMBER(10),
name VARCHAR2(100),
active NUMBER(1)
)
PARTITION BY LIST(active)
(
PARTITION active_records VALUES (0)
PARTITION inactive_records VALUES (1)
);
Если хотите, можете поместить каждый раздел в разные табличные пространства. Вы также можете разделить свои индексы.
Между прочим, это похоже на повторение вопроса это, как новичок, я должен спросить, какова процедура работы с непреднамеренными дубликатами?
Редактировать: Как указано в комментариях, предоставлен пример создания многораздельной таблицы в Oracle.
Не могли бы вы уточнить, как «разбить» таблицу. Я имею в виду дать код для любой RDBM, которая вам нравится.
По запросу добавлен пример многораздельной таблицы. Обратитесь к руководству Oracle Concepts для получения подробной информации о секционировании таблиц и индексов. Я использую Oracle 10.2 и ссылаюсь на всю документацию отсюда -> oracle.com/pls/db102/homepage
Вместо «активного» флага я бы рекомендовал использовать другое имя поля, например, «удалено». Причина в том, что когда следующий человек работает над этим, он может быть сбит с толку тем, что означает «активный». Кроме этого, +1 отличный пост.
Удаленный @NotMe кажется столь же неоднозначным. Если что-то удалено, почему это все еще есть? Похоже, что с подобными вещами лучше справиться с помощью документации.
Мы используем оба метода для работы с неактивными записями. Используемый нами метод зависит от ситуации. Для записей, которые по сути являются значениями поиска, мы используем поле «Активный бит». Это позволяет нам деактивировать записи, чтобы они не использовались, но также позволяет нам поддерживать целостность данных с отношениями.
Мы используем метод «перейти к разделительной таблице», когда данные больше не нужны и данные не являются частью отношения.
Ситуация действительно диктует решение, мне кажется:
Если в таблице есть пользователи, то можно использовать несколько «флаговых» полей. Один для «Удалено», «Отключено» и т. д. Или, если пространство является проблемой, тогда будет достаточно флага для отключения, а затем фактическое удаление строки, если они были удалены.
Это также зависит от политик хранения данных. Если существуют политики для хранения данных в архиве, то по прошествии длительного времени, скорее всего, потребуется отдельная таблица.
Нет - это довольно распространенная вещь - несколько вариантов в зависимости от конкретных требований (но вы их уже рассмотрели):
1) Если вы ожидаете иметь целую СУМКУ данных - например, несколько терабайт или более - неплохая идея немедленно заархивировать удаленные записи - хотя вы можете использовать комбинированный подход, помечая как удаленные, а затем копируя в архивные таблицы.
2) Конечно, возможность жесткого удаления записи все еще существует - хотя мы, разработчики, как правило, являемся пакостниками данных - я предлагаю вам взглянуть на бизнес-процесс и решить, есть ли теперь необходимость даже хранить данные - если есть - сделайте так ... если нет - вы, вероятно, можете смело просто выбросить этот материал ... опять же, в соответствии с конкретным бизнес-сценарием.
Мы используем перечисление («АКТИВНЫЙ», «НЕАКТИВНЫЙ», «УДАЛЕННЫЙ») в большинстве таблиц, поэтому на самом деле у нас есть трехсторонний флаг. Я считаю, что это хорошо работает для нас в разных ситуациях. Ваш пробег может отличаться.
Перемещение неактивных вещей - обычно глупая идея. Это много накладных расходов с большим потенциалом для ошибок, все становится более сложным, например, разархивирование материала и т. д. Что вы делаете со связанными данными? Если вы переместите все это, вам придется изменить каждый запрос. Если вы не переместите его, какое преимущество вы надеялись получить?
Это приводит к следующему вопросу: ПОЧЕМУ бы вы его переместили? Правильно проиндексированная таблица требует одного дополнительного поиска, когда размер увеличивается вдвое. Любое улучшение производительности будет незначительным. И зачем вам вообще думать об этом до тех пор, пока не наступит далекое будущее, когда у вас действительно возникнут проблемы с производительностью?
Я думаю, что если смотреть на это строго как на часть данных, то способ, показанный в исходном посте, является правильным. Активная часть данных флага напрямую зависит от первичного ключа и должна быть в таблице.
В этой таблице хранятся данные о людях независимо от текущего статуса их данных.
С «пуристской точки зрения» реальная модель не делает различий между представлением и таблицей - оба являются отношениями. Таким образом, использование представления, использующего дискриминатор, является совершенно осмысленным и допустимым при условии, что объекты правильно названы, например. Человек / ActivePerson.
Кроме того, с «пуристской точки зрения» таблица должна называться person, а не people, поскольку имя отношения отражает кортеж, а не весь набор.
схемы именования являются предпочтением. Я думаю, что просто рекомендуется придерживаться того, как вы решаете для всех таблиц. Многим нравится считать, что отношение содержит множество элементов.
Подобные двоичные флаги в вашей схеме - ПЛОХАЯ идея. Рассмотрим запрос
SELECT count(*) FROM users WHERE active=1
Выглядит достаточно просто. Но что происходит, когда у вас большое количество пользователей, настолько много, что потребуется добавить индекс в эту таблицу. Опять же, это выглядит прямо вперед
ALTER TABLE users ADD INDEX index_users_on_active (active)
КРОМЕ!! Этот индекс бесполезен, потому что количество элементов в этом столбце ровно два! Любой оптимизатор запросов к базе данных проигнорирует этот индекс из-за его низкой мощности и выполнит сканирование таблицы.
Прежде чем заполнять схему полезными флагами, подумайте, как вы собираетесь получить доступ к этим данным.
https://stackoverflow.com/questions/108503/mysql-advisable-number-of-rows
Количество элементов не должно влиять на использование индекса. Избирательность.
Что касается индексации логического значения, почему бы и нет:
ALTER TABLE users ADD INDEX index_users_on_active (id, active) ;
Разве это не улучшило бы поиск?
Однако я не знаю, насколько этот ответ зависит от платформы.
Это старый вопрос, но для тех, кто ищет индексы низкой мощности / селективности, я хотел бы предложить следующий подход, который позволяет избежать секционирования, вторичных таблиц и т. Д .:
Уловка состоит в том, чтобы использовать столбец dateInactivated, в котором хранится отметка времени, когда запись деактивирована / удалена. Как следует из названия, значение равно ПУСТО (NULL), пока запись активна, но после деактивации введите системную дату и время. Таким образом, индекс в этом столбце имеет высокую селективность по мере роста числа «удаленных» записей, поскольку каждая запись будет иметь уникальное (не строго говоря) значение.
Тогда ваш запрос станет:
SELECT * FROM people WHERE dateInactivated is NULL;
Индекс будет включать только нужный вам набор строк.
Фильтрация данных по битовому флагу для больших таблиц не очень хороша с точки зрения производительности. В случае «активного» детерминированного виртуального удаления вы можете создать таблицу «TableName_delted» с такой же структурой и перемещать туда удаленные данные с помощью триггера удаления.
Это решение поможет повысить производительность и упростит запросы данных.
Я также хочу перейти к подходу с двумя таблицами, поскольку я работаю над старой, плохо спроектированной базой данных, в которой некоторые таблицы имеют столбец «active = 'T / F'» для целей аудита и у них нет первичных ключей. Как вы обрабатывали удаленные записи, используете ли вы флаг, чтобы пометить строку как активную / удаленную, или вы также перемещаете удаленную запись в таблицу истории? Кроме того, вы каскадно перемещаете все связанные данные в таблицы истории? Спасибо!