MySql Primary Key> 900/1000 байт? - PullRequest
1 голос
/ 07 июня 2009

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

MySql не любит длинные первичные ключи . Это можно обойти? Возможно, только для обеспечения уникальности, без создания индекса?

Я бы не хотел использовать ASCII вместо UTF8 только для включения первичного ключа (символ UTF8 занимает 3 байта).

Моя таблица определена следующим образом:

CREATE TABLE `configuration` (
  `Section` varchar(200) NOT NULL,
  `StoredKey` VARCHAR(200) NOT NULL,
  `ServiceName` VARCHAR(300) NOT NULL,
  `ServiceMajorVersion` int unsigned NOT NULL,
  `ServiceMinorVersion` int unsigned NOT NULL,
  `ServiceInstanceID` VARCHAR(100) NOT NULL,
  `StoredValue` VARCHAR(1024)

 , PRIMARY KEY (`Section`, `StoredKey`, `ServiceName`, `ServiceMajorVersion`, `ServiceMinorVersion`, `ServiceID`)   
 )  ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Ответы [ 5 ]

4 голосов
/ 08 июня 2009

@ porneL имеет правильный ответ для этого случая, однако @ Cade Roux и @ noonex также верны: базы данных не предназначены для использования как Excel.

У вас должны быть дополнительные таблицы:

CREATE TABLE ServiceInstance (
    ID int(11) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
    Hash binary(16) NOT NULL,
    ServiceInstanceID varchar(100) NOT NULL,
    UNIQUE(Hash)
);

Для каждой таблицы, кроме данных, которые будут уникальными для каждой строки конфигурации.

Когда вы вставляете, делайте:

INSERT INTO ServiceInstance (Hash, ServiceInstanceID) VALUES (unhex(md5('whatever')), 'whatever');

Тогда ваша основная таблица становится:

CREATE TABLE `configuration` (
    `Section_ID`          int unsigned NOT NULL,
    `StoredKey_ID`        int unsigned NOT NULL,
    `ServiceName_ID`      int unsigned NOT NULL,
    `ServiceMajorVersion` int unsigned NOT NULL,
    `ServiceMinorVersion` int unsigned NOT NULL,
    `ServiceInstanceID`   int unsigned NOT NULL,
    `StoredValue`         VARCHAR(1024),
    UNIQUE (`Section_ID`, `StoredKey_ID`, `ServiceName_ID`, `ServiceMajorVersion`, `ServiceMinorVersion`, `ServiceInstanceID`)   
 )  ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Вместо этого используйте ключ UNIQUE, так как ПЕРВИЧНЫЕ КЛЮЧИ обычно используются, когда вы всегда будете получать доступ к строкам по первичному ключу. Если это просто ограничение, используйте UNIQUE.

4 голосов
/ 07 июня 2009

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

3 голосов
/ 07 июня 2009

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

В качестве альтернативы вы можете попробовать использовать binary(16) в качестве первичного ключа с unhex(md5(concat( столбцами ))) в качестве значения.

2 голосов
/ 07 июня 2009

Трудно сказать без понимания вашей базы данных, но, возможно, потребуется некоторая нормализация. Вы всегда можете сделать UNIQUE INDEX, который не является первичным ключом, и если уже есть один столбец, который будет уникальным, сделать его первичным ключом, а если его нет, вы можете сделать суррогатный первичный ключ (INTEGER AUTO_INCREMENT).

0 голосов
/ 07 июня 2009

Согласитесь с тем, что @pornel и @CadeRoux уже выложили; Вам лучше создать суррогатный первичный ключ (ConfigurationId) в виде целочисленного столбца с автоинкрементом, а затем создать отдельный уникальный индекс.

...