Почему составные клавиши обескуражены в спящем режиме?
Это из Официальное руководство Hibernate:
Существует альтернативное объявление <composite-id>
, которое позволяет получить доступ к устаревшим данным с помощью составных клавиш. Его использование сильно не рекомендуется ни для чего другого.
Почему составные клавиши обескуражены? Я рассматриваю возможность использования таблицы с тремя столбцами, где все столбцы являются внешними ключами и вместе образуют первичный ключ, который является содержательной связью в моей модели. Я не понимаю, почему это плохая идея, особенно, что я буду использовать для них индекс.
Какая альтернатива? Создать дополнительный автоматически созданный столбец и использовать его в качестве первичного ключа? Мне все равно нужно запросить мои 3 столбца в любом случае!?
Короче говоря, почему это утверждение верно? и какая лучшая альтернатива?
Ответы
Ответ 1
Они отговаривают их по нескольким причинам:
- они громоздки в использовании. Каждый раз, когда вам нужно ссылаться на объект (или строку), для примера в вашем веб-приложении вам нужно передать 3 параметра, а не только один.
- они неэффективны. Вместо простого хэширования целого числа, база данных должна содержать хеширование из 3 столбцов.
- они приводят к ошибкам: разработчики неизбежно внедряют методы equals и hashCode класса первичного ключа неправильно. Или они делают его изменчивым и изменяют свое значение после его хранения в HashSet или HashMap
- они загрязняют схему. Если другой таблице необходимо ссылаться на эту таблицу с тремя столбцами, ей необходимо будет иметь только 3 столбца вместо одного в качестве внешнего ключа. Теперь предположим, что вы следуете одному и тому же дизайну и сделаете эту внешнюю ключевую часть из трех столбцов первичного ключа этой новой таблицы, вы быстро получите первичный ключ из 4 столбцов, а затем 5-столбцовую PK в следующей таблице и т.д. и т.д., что приводит к дублированию данных и грязной схеме.
Альтернативой является наличие одного столбца, автоматически сгенерированного первичного ключа, в дополнение к другим трем столбцам. Если вы хотите, чтобы кортеж из трех столбцов был уникальным, используйте уникальное ограничение.
Ответ 2
Даже если это возможно - возможно, слишком поздно, чтобы ответить на ваш вопрос, я хочу здесь дать еще одну точку зрения (более умеренную, я надеюсь) на необходимость (это действительно совет?) Hibernate использовать суррогатные ключи.
Прежде всего, я хочу четко сказать, что оба суррогатные ключи (искусственные автоматически сгенерированные) и натуральные ключи (состоящие из столбцов (столбцов) с доменным значением) имеют профи и минус. Я не пытаюсь сказать, что один ключевой тип лучше другого. Я пытаюсь сказать, что в зависимости от ваших требований естественные ключи могут быть лучшим выбором, чем суррогатные, и наоборот.
Мифы на натуральных клавишах
- Композитные клавиши менее эффективны, чем суррогатные ключи. Нет! Это зависит от используемого механизма базы данных:
- Природные ключи не существуют в реальной жизни. Извините, но они существуют! В авиационной промышленности, например, следующий кортеж будет всегда уникальным в отношении данного запланированного полета (авиакомпания, departureDate, flightNumber, operatingSuffix). В более общем плане, когда набор бизнес-данных гарантированно будет уникальным по заданному стандарту, тогда этот набор данных является [хорошим] кандидатом на естественный ключ.
- Натуральные клавиши "загрязняют схему" дочерних таблиц. Для меня это скорее чувство, чем реальная проблема. Наличие первичного ключа из 4 столбцов по 2 байта может быть более эффективным, чем один столбец из 11 байтов. Кроме того, 4 столбца могут использоваться для непосредственного запроса дочерней таблицы (с использованием 4 столбцов в предложении where) без присоединения к родительской таблице.
Недостатки суррогатных ключей
Суррогатные клавиши:
- Источник проблем с производительностью:
- Обычно они реализуются с использованием автоинкрементных столбцов, что означает:
- Обратная связь с базой данных каждый раз, когда вы хотите получить новый идентификатор (я знаю, что это можно улучшить с помощью кеширования или алгоритмов [seq] hilo, но все же эти методы имеют свои недостатки).
- Если в один день вам нужно переместить свои данные из одной схемы в другую (это происходит довольно регулярно в моей компании), вы можете столкнуться с проблемами столкновения с идентификаторами. И да, я знаю, что вы можете использовать UUID, но для последних требуется 32 шестнадцатеричных цифры! (Если вы заботитесь о размере базы данных, это может быть проблемой).
- Если вы используете одну последовательность для всех своих суррогатных ключей, то, наверняка, в вашей базе данных вы столкнетесь с разногласиями.
- Ошибка. Последовательность имеет предел max_value, поэтому - как разработчик - вы должны обратить внимание на следующие факты:
- Вы должны выполнить цикл (когда достигнуто максимальное значение, оно возвращается к 1,2,...).
- Если вы используете последовательность в качестве порядка (по времени) ваших данных, тогда вы должны обрабатывать случай циклирования (столбец с Id 1 может быть более новым, чем строка с максимальным значением Id - 1).
- Убедитесь, что ваш код (и даже ваши клиентские интерфейсы, которые не должны выполняться, поскольку он должен быть внутренним идентификатором) поддерживает целые числа 32b/64b, которые вы использовали для хранения ваших значений последовательности.
- Они не гарантируют дублирование данных. Вы всегда можете иметь 2 строки со всеми одинаковыми значениями столбцов, но с другим сгенерированным значением. Для меня это проблема THE суррогатных ключей с точки зрения дизайна базы данных.
- Подробнее в Википедии...
Почему Hibernate предпочитает/нуждается в суррогатных ключах?
Как указано в Java Persistence with Hibernate:
Более опытные пользователи Hibernate используют исключительно saveOrUpdate(); его гораздо проще позволить Hibernate решить, что нового и что старое, особенно в более сложной сети объектов со смешанным состоянием. только (не очень серьезный) недостаток эксклюзивного saveOrUpdate() что он иногда не может догадаться, является ли экземпляр старым или новым без запуска SELECT в базе данных, например, когда класс сопоставлен с естественным составным ключом и без версии или временной метки свойство.
Некоторые проявления ограничения (вот как, я думаю, мы должны это назвать) можно найти здесь.
Заключение
Пожалуйста, не стесняйтесь мнения. Используйте естественные ключи, когда это имеет значение для этого, и используйте суррогатные ключи, когда их лучше использовать.
Надеюсь, что это помогло кому-то!
Ответ 3
Я рассмотрел бы проблему с дизайнерской точки зрения. Это не просто, если Hibernate считает их хорошими или плохими. Реальный вопрос: являются ли естественные ключи хорошими кандидатами хорошими идентификаторами для моих данных?
В вашей бизнес-модели сегодня может быть удобно идентифицировать запись по некоторым данным, но бизнес-модели развиваются во времени. И когда это произойдет, вы обнаружите, что ваш естественный ключ больше не подходит для уникальной идентификации ваших данных. И с ссылочной целостностью в других таблицах это приведет к тому, что вещи MUCH сложнее изменить.
Наличие суррогатного ПК удобно, потому что оно не связано с тем, как ваши данные идентифицируются в вашем хранилище с вашей структурой бизнес-модели.
Естественные ключи не могут быть сгенерированы из последовательности, а случай данных, которые не могут быть идентифицированы по его данным, намного чаще. Это свидетельствует о том, что натуральные ключи отличаются от ключа хранения, и они не могут рассматриваться как общий (и хороший) подход.
Использование суррогатных ключей упрощает дизайн приложения и базы данных. Они проще в использовании, более эффективны и прекрасно работают.
Природные клавиши приносят только недостатки: я не могу придумать единственное преимущество для использования естественных ключей.
Тем не менее, я думаю, что у спящего режима нет реальных проблем с естественными (сложенными) ключами. Но вы, вероятно, иногда обнаружите некоторые проблемы (или ошибки), а также проблемы с документацией или пытаетесь получить помощь, потому что сообщество спящего режима широко признает преимущества суррогатных ключей. Итак, подготовьте хороший ответ за то, почему вы выбрали составной ключ.
Ответ 4
Приложения, разработанные с базой данных в качестве инструмента, безусловно, более полезны для поддержания потока операций над суррогатными ключами, используя кластерные индексы для оптимизации запросов.
Особое внимание необходимо уделять системам хранения данных и систем стиля OLAP, которые используют массивную таблицу фактов, чтобы связать суррогатные ключи размеров вместе. В этом случае данные диктуют панель/приложение, которое может использоваться для ведения записей.
Таким образом, вместо того, чтобы один метод был предпочтительнее другого, возможно, это одна из директив выгодна другой, для построения ключа: вы не сможете быстро разрабатывать приложение Hibernate для непосредственного доступа к экземпляру системы SSAS.
Я разрабатываю с использованием обеих ключевых смесей и чувствую, что для реализации сплошной звезды или рисунка снежинки суррогат с кластеризованным индексом обычно является моим первым выбором.
Итак, с точки зрения OP и других, которые ищут: если вы хотите остаться db-инвариантом с вашей разработкой (в которой Hibernate специализируется) - используйте суррогатный метод, и когда чтение данных имеет тенденцию замедляться или вы замечаете некоторые запросы дренируют производительность, возвращаются к вашей конкретной базе данных и добавляют составные, кластерные индексы, которые оптимизируют порядок запросов.
Ответ 5
Если документация Hibernate правильно понята:
"Существует альтернативное объявление <composite-id>
, которое разрешает доступ к устаревшим данным с составными ключами. Его использование сильно не рекомендуется ни для чего другого".
по теме 5.1.4. id тега xml <id>
, который позволяет скопировать первичное ключевое отображение слишком рано, мы можем заключить, что в документации на спящий режим не рекомендуется использовать <composite-id>
вместо тега <id>
xml для композитного отображения первичного ключа и НЕ сделайте любую ссылку отрицательной для использования составных первичных ключей.