REST API первичный ключ дизайн MySQL - PullRequest
0 голосов
/ 16 мая 2018

Мы создаем новый REST API и должны принять несколько решений относительно первичного ключа и idempotency_key.В нашем API много пользователей, и пользователям разрешено только искать принадлежащие им объекты.Запросы аутентифицируются, поэтому мы знаем userId, связанный с данным запросом.

Свойства, о которых идет речь:

  • userId Идентификатор пользователя.
  • idempotenyKey Ключ идемпотентности, используемый в идемпотентных запросах к API. Уникальный для пользователя.

Предположим, есть гипотетическая таблица Cars с конечной точкой GET .../cars/{id}, на которой мы будем основывать наше обсуждение.

Параметры

Вариант 1 - использовать составной идентификатор пользователя и idempotencyKey в качестве первичного ключа

CREATE TABLE Cars (
 userId VARCHAR(255) NOT NULL,
 idempotencyKey VARCHAR(255) NOT NULL,
 description VARCHAR(255),
 PRIMARY KEY (userId, idempotencyKey),
 INDEX user_index (userId)
);

Элемент поиска: GET .../cars/{idempotencyKey}

Мысли:

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

Вариант 2 - Использование хеша userId + idempotencyKey в качестве первичного ключа

CREATE TABLE Cars (
 id VARCHAR(255) NOT NULL,
 userId VARCHAR(255) NOT NULL,
 idempotencyKey VARCHAR(255) NOT NULL,
 description VARCHAR(255),
 PRIMARY KEY (id),
 INDEX user_index (userId)
);

При вставке мы вычисляем id = hash(userId + idempotencyKey).

Элемент поиска: GET .../cars/{id}

Мысли:

  • Первичные ключи не поддаются проверке.
  • Это дополнительно предотвращает возможность угроз безопасности для операцийпротив ids.
  • Больше не является составным первичным ключом.
  • В отличие от варианта 3, не требует уникального ограничения для (userId, idempotencyKey).

Вариант 3 - Генерация первичного ключа uuid

CREATE TABLE Cars (
 id VARCHAR(255) NOT NULL,
 userId VARCHAR(255) NOT NULL,
 idempotencyKey VARCHAR(255) NOT NULL,
 description VARCHAR(255),
 PRIMARY KEY (id),
 INDEX user_index (userId),
 CONSTRAINT unique_by_user UNIQUE (userId, idempotencyKey)
);

При вставке мы установили id = UUID.randomUUID().

Поиск элемента: GET .../cars/{id}

Мысли:

  • Идентификатор абсолютно неуверен и не привязан к каким-либо бизнес-данным.
  • Требуетсядополнительный индекс.

Вариант 4 - автоинкрементный первичный ключ, который никогда не предоставляется пользователю

CREATE TABLE Cars (
 id INT NOT NULL AUTO_INCREMENT,
 userId VARCHAR(255) NOT NULL,
 idempotencyKey VARCHAR(255) NOT NULL,
 description VARCHAR(255),
 PRIMARY KEY (id),
 INDEX user_index (userId),
 CONSTRAINT unique_by_user UNIQUE (userId, idempotencyKey)
);

Существует несколько способовсделать поиск.Поиск может быть основан исключительно на idempotencyKey, то есть: GET .../cars/{idempotencyKey}

В качестве альтернативы, мы можем автоматически сгенерировать ссылочный идентификатор UUID, который будет проиндексирован и использован для поиска.

Мысли:

  • Первичный ключ никогда не предоставляется пользователю, что является довольно распространенной практикой.
  • Обеспечивает большую гибкость при изменении бизнес-логики (хотя для фундаментальных концепций, таких как userId и idempotencyKey, я не вижу, как они изменились бы).
  • Первичный ключ - INT и, таким образом,меньше.Это учитывает меньшие индексы и возможно большую производительность.
  • Снова требуется дополнительный индекс.

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

Спасибо!

...