Подтвердить что ты не робот

Композитные первичные ключи: хорошо это или плохо

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

Я хочу хранить платежи для заказов в отдельной таблице. Причина в том, что в заказе может быть много элементов, которые обрабатываются в отдельной таблице в виде отношений от многих до многих. Теперь, если я не использую составные первичные ключи для моей таблицы платежей, я потеряю свой уникальный PaymentID:

[PaymentId] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[OrderId] INT NOT NULL PRIMARY KEY --Also a Foreign Key--

Теперь, если я просто удалю основной ключ для OrderId, я потеряю одно-одно отношение здесь, поэтому Many OrderIds can be associated to many PaymentIds, и я не хочу этого.

Вот почему ранее заданные здесь вопросы заключили (в основном), что составной ключ - плохая идея. Поэтому я хочу прояснить это для себя; если это плохо, тогда какая лучшая практика?

4b9b3361

Ответ 1

Нет вывода, что составные первичные ключи плохие.

Лучшей практикой является наличие некоторых столбцов или столбцов, которые однозначно идентифицируют строку. Но в некоторых таблицах один столбец сам по себе недостаточно, чтобы однозначно идентифицировать строку.

SQL (и реляционная модель) позволяет использовать составной первичный ключ. В некоторых случаях это хорошая практика. Или другой способ взглянуть на это - это не плохая практика во всех случаях.

Некоторые люди считают, что каждая таблица должна иметь целочисленный столбец, который автоматически генерирует уникальные значения и должен служить в качестве первичного ключа. Некоторые люди также утверждают, что этот первичный ключевой столбец всегда следует называть id. Но это конвенции, не обязательно лучшие практики. У конвенций есть определенная польза, поскольку она упрощает определенные решения. Но конвенции также являются ограничительными.

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

Я бы разработал систему, которую вы описываете следующим образом:

Products  : product_id (PK)

Orders    : order_id (PK)

LineItems : product_id is (FK) to Products
            order_id is (FK) to Orders
            (product_id, order_id) is (PK)

Payments  : order_id (FK)
            payment_id - ordinal for each order_id
            (order_id, payment_id) is (PK)

Это также связано с концепцией идентификации отношений. Если он определяет, что платеж существует только потому, что существует порядок, тогда сделайте часть заказа первичного ключа.

Обратите внимание, что в таблице LineItems также отсутствует собственный автоинкремент, первичный ключ с одним столбцом. Таблица "многие ко многим" является классическим примером хорошего использования составного первичного ключа.

Ответ 2

Этот вопрос опасно близок к тому, чтобы просить мнения, которые могут порождать религиозные войны. Как человек, который очень предвзято относится к тому, что в моих таблицах автоматически увеличиваются целые первичные ключи (что называется TablenameId, а не `Id), есть одна ситуация, когда она является необязательной.

Я думаю, что другие ответы касаются того, зачем вам нужны первичные ключи.

Одна очень важная причина для справочных целей. В реляционной базе данных любой объект может - в теории - ссылаться на другой объект через отношения внешних ключей. Для внешних ключей вы определенно хотите, чтобы один столбец однозначно определял строку. В противном случае вам придется иметь дело с несколькими столбцами в разных таблицах, которые выравниваются друг с другом. Это возможно, но громоздко.

Таблица, на которую вы ссылаетесь, не является таблицей "сущность", она является таблицей "соединения". Это реляционная база данных для обработки отношений "многие ко многим". Поскольку он не представляет собой сущность, он не должен иметь отношения с внешним ключом. Следовательно, составной первичный ключ является разумным. Есть некоторые ситуации, например, когда вы обеспокоены размером базы данных, где желательно оставить искусственный первичный ключ.

Ответ 3

Лучшая практика - это всегда самое лучшее для вашего приложения. Не смотрите на произвольные "наилучшие подходы", иначе вы все равно можете оказаться в худшем приложении.

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

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

Как и во всех технических решениях, действует его баланс. Является ли снижение производительности выгодным?

Другим решением, которое очень распространено, является использование так называемого суррогатного ключа, а затем применить уникальное ограничение индекса для ключей, которые должны быть уникальными в комбинации. Это делает поиск в таблице менее сложным, поскольку он включает только обычный индекс.

Ответ 4

Дисковое пространство дешево, поэтому первичный ключ, сгруппированный по идентификатору int (1,1), названному после соглашения (например, имя таблицы pk +), является хорошей практикой. Это упростит управление запросами, объединениями, индексами и другими ограничениями.

Однако есть одна веская причина: не нужно (в MS SQL Server): если вы хотите управлять физической сортировкой ваших данных в базовой системе хранения.

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

Ответ 5

Платеж можно рассматривать как заказ, поэтому я имею тенденцию иметь всего две таблицы, одну таблицу для заказов (биллинг, данные о доставке, идентификатор платежа) и один для элементов в заказе (название продукта, количество, цена).

Идентификатор заказа может быть основным Первичным ключом, и у вас может быть только ограничение уникальности для идентификатора платежа. Или, если идентификатор заказа и идентификатор платежа являются идентификатором в целом, вы можете создать поле идентификатора, которое автоматически увеличивается.