Генерация первичного ключа без использования базы данных - PullRequest
5 голосов
/ 26 августа 2010

Недавно я столкнулся с вопросом, касающимся «Генерации первичного ключа в кластерной среде из 5 серверов приложений - [OAS Версия 10] без использования базы данных».

Обычно мы генерируем PK с помощью последовательности БДили сохранение значений в таблице базы данных, а затем использование SP для генерации нового значения PK ... Однако текущее требование заключается в создании первичного ключа для моего приложения без ссылки на базу данных с использованием JDK 1.4.

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

Спасибо,

Ответы [ 9 ]

8 голосов
/ 26 августа 2010

Используйте UUID в качестве основного ключа и создайте на стороне клиента.

Edit:
После вашего комментария я почувствовал, что должен остановиться на том, почему это хороший способ сделать что-то.

Хотя последовательные первичные ключи являются наиболее распространенными в базах данных, использование случайно сгенерированного первичного ключа часто является лучшим выбором для распределенных баз данных или (особенно) баз данных, которые поддерживают «отключенный» пользовательский интерфейс, то есть пользовательский интерфейс, где пользователь не является постоянно подключен к базе данных в любое время.

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

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

С другой стороны, UUID - это 16 байтов, а не стандартный 4-байтовый int - в 4 раза больше места. Это действительно проблема в эти дни? Я бы сказал, что нет, но я знаю некоторых, которые будут спорить иначе. Единственная реальная проблема производительности, когда дело доходит до UUID - это индексация, в частности кластеризованная индексация. Я собираюсь проникнуть в мир SQL Server, так как я не так часто разрабатываю для Oracle, и это моя текущая зона комфорта, и расскажу о том факте, что SQL Server по умолчанию создаст кластерный индекс для всех полей в первичный ключ таблицы. Это довольно хорошо работает в мире auto-increment int и обеспечивает хорошую производительность при поиске на основе ключей. Однако любой DBA, достойный его соли, будет кластеризоваться по-другому, но люди, которые не обращают внимания на эту кластеризацию и которые также используют UUID (GUID в мире Microsoft), имеют тенденцию к некоторым неприятным замедлениям для баз данных с высокой вставкой, поскольку кластеризованные Индекс должен пересчитываться при каждой вставке, и если он кластеризован на основе UUID, который может поместить новый ключ в середину кластеризованной последовательности, возможно, потребуется перегруппировать данные lot для поддержки кластеризованного индекса. , Это может или не может быть проблемой в мире Oracle - я просто не знаю, кластеры Oracle по умолчанию кластеризованы, как в SQL Server.

Если за этим предложением о выполнении было слишком сложно следовать, просто запомните следующее: если вы используете UUID в качестве первичного ключа, не кластеризуйте по этому ключу !

3 голосов
/ 26 августа 2010

Может оказаться полезным поискать генерацию UUID.

В простом случае, когда одна программа запускает один поток на каждой машине, вы можете сделать что-то, например,

MAC address + time in nanseconds since 1970.
2 голосов
/ 26 августа 2010

Взгляните на эти стратегии , используемые Hibernate (раздел 5.1.5 в ссылке).Вы обязательно найдете это полезным.Он объясняет несколько методов, их плюсы и минусы, а также указывает, безопасны ли они в кластерной среде.

Лучше всего, есть доступный код, который уже реализует его для вас:

2 голосов
/ 26 августа 2010

Вы должны рассмотреть возможность использования идентификаторов в форме UUID. Java5 имеет класс для их представления (и также должен иметь фабрику для их генерации). С помощью этого фабричного класса вы можете перенести код в вашу антивирусную версию Java 1.4, чтобы получить требуемые идентификаторы.

2 голосов
/ 26 августа 2010

Если вы не можете использовать базу данных вообще , GUID / UUID - единственный надежный способ.Однако, если вы можете использовать базу данных иногда , попробуйте алгоритм HiLo .

0 голосов
/ 28 августа 2010

Вот как это делается в MongoDB: http://www.mongodb.org/display/DOCS/Object+IDs

Они включают метку времени.

Но вы также можете установить Oracle Express и выбрать последовательности, которые вы можете выбрать оптом:

SQL> выбрать mysequence.nextval из двойного соединения по уровню <20; </p>

NEXTVAL

     1
     2
     3
     4
     5
    ..  
    20

Почему вы не можете использовать базу данных?Деньги (Oracle Express бесплатен) или единая точка отказа?Или вы хотите поддерживать другие базы данных, кроме Oracle, в будущем?

0 голосов
/ 26 августа 2010

с помощью объекта Statement вы можете вызывать Statement.getGeneratedKeys ();метод для получения автоматически сгенерированных ключей, сгенерированных при выполнении этого объекта Statement.

Java doc

0 голосов
/ 26 августа 2010

Вы можете сгенерировать ключ на основе комбинации трех нижеуказанных вещей

  1. IP-адрес или MAC-адрес устройства
  2. Текущее время
  3. Инкрементный счетчик в каждом экземпляре (чтобы один и тот же ключ не генерировался дважды на одной машине, поскольку время может казаться одинаковым при двух непосредственных созданиях ключей из-за точности времени)
0 голосов
/ 26 августа 2010

Если это подходит вашему приложению, вы можете использовать больший строковый ключ в сочетании с функцией UUID () или SHA1 (случайных данных).

Для последовательных int'ов я оставлю это другому постеру.

...