Запрос мнений: одна последовательность для всех таблиц
Вот еще один, о котором я думал в последнее время.
В более ранних обсуждениях мы пришли к выводу: "естественные первичные ключи плохи, искусственные первичные ключи хороши".
Ранее работая с Hibernate, я видел, что Hibernate по умолчанию создает одну последовательность для всех таблиц. Сначала я был озадачен этим, зачем вы это делаете. Но позже я увидел преимущество в том, что он заставляет связывать родителей и детей с дураком. Поскольку таблицы не имеют одного и того же значения первичного ключа, случайная привязка родителя к таблице, которая не является дочерней, не дает никаких результатов.
Кто-нибудь видит недостатки этого подхода. Я вижу только одно: у вас не может быть более 99999999999999999999999999999 записей в вашей базе данных.
Ответы
Ответ 1
В зависимости от того, как последовательности реализованы в базе данных, всегда ударять по одной и той же последовательности может быть лучше или хуже. Когда только несколько или только один поток запрашивает новые значения, проблем с блокировкой не будет. Но плохая реализация может вызвать перегрузку.
Еще одна проблема заключается в откатах транзакций: последовательности не откатываются (потому что кто-то еще мог запросить более высокое значение уже), поэтому вы можете иметь большие пробелы, которые будут потреблять ваше числовое пространство намного быстрее, чем вы могли ожидать. OTOH, потребуется некоторое время, чтобы съесть 2 или 4 миллиарда идентификаторов (если вы "используете" только 32-битные (подписанные) ints), поэтому на практике это редко бывает проблемой.
Наконец, вы не можете легко reset выполнить последовательность, если вам нужно. Но если вам нужно перезапустить последовательность (например, количество записей с полуночи), вы можете указать Hibernate создать/использовать вторую последовательность.
Основным преимуществом является то, что вы можете уникально идентифицировать объекты в любом месте БД только по идентификатору. Это означает, что вы можете серьезно сократить информацию журнала, которую вы пишете в производственной системе, и все равно найти что-то, если у вас есть только ID.
Ответ 2
Могут возникнуть проблемы с производительностью, когда весь код получает значения из одной последовательности - см. this Ask Tom thread.
Ответ 3
Я предпочитаю иметь одну последовательность в таблице. Это происходит из одного общего наблюдения: некоторые таблицы ( "мастер-таблицы" ) имеют относительно небольшое количество строк и должны храниться "навсегда". Например, таблица клиентов в ERP.
В других таблицах ( "таблицы транзакций" ) многие строки генерируются вечно, но через некоторое время эти строки могут быть заархивированы (или просто удалены). Самый экстремальный пример - таблица трассировки, используемая для целей отладки; он может вырасти на сотни строк в секунду, но каждая строка устаревает через несколько дней.
Маленькие идентификаторы в основных таблицах облегчают работу непосредственно в базе данных, например. для целей отладки.
select * from orders where customerid=415
против
select * from orders where customerid=89461836571
Но это лишь незначительная проблема. Большей проблемой является велоспорт. Если вы используете одну последовательность для всех таблиц, вы просто не можете ее перезапустить. С одной последовательностью в таблице вы можете перезапустить последовательности для таблиц транзакций, когда вы заархивировали или удалили старые данные. У мастер-таблиц практически нет такой проблемы, так как они растут намного медленнее.
Я вижу мало значения, имея только одну последовательность для всех таблиц. Доводы до сих пор не убеждают меня.
Ответ 4
Существует несколько недостатков использования одной последовательности: -
- приведенный concurrency. Передача следующего значения последовательности включает синхронизацию. На практике я не думаю, что это может быть большой проблемой.
- У Oracle есть специальный код, поддерживающий индексы btree для обнаружения монотонно возрастающих значений и правильного баланса дерева
- У CBO может быть лучшее время для оценки запросов диапазона по индексу (если вы когда-либо делали это), если большинство значений было заполнено
Преимущество может заключаться в том, что вы можете определить порядок вставок среди разных таблиц.
Ответ 5
Конечно, есть плюсы и минусы для подхода с одной последовательностью и однопользовательской таблицей. Лично я нахожу способность назначать поистине уникальный идентификатор для строки, делая каждый столбец id uuid достаточным для того, чтобы перевесить все недостатки. Как пишет Аарон Д., лаконично пишет:
вы можете уникально идентифицировать объекты в любом месте БД только с помощью идентификатора
И для большинства приложений из-за того, что Hibernate3 выполняет пакетные инструкции IMPORT, это не будет узким местом производительности, если массивные количества записей не будут бороться за один и тот же ресурс базы данных (SELECT hibernate_sequence.nextval FROM dual).
Кроме того, это сопоставление последовательностей не поддерживается в последней версии (1.2) Grails. Хотя он был поддержан в Grails 1.1 (!). Теперь это требует подкласса одного из диалектных классов Hibernate в качестве обходного пути.
Для тех, кто использует Grails/GORM, посмотрите эту запись JIRA:
Отображения Oracle Sequence игнорируются