Случайные строки для идентификации записи? - PullRequest
0 голосов
/ 28 июня 2018

Я хочу сделать что-то похожее на то, что делают imgur и большинство других веб-сайтов: я хочу использовать случайную строку в URL-адресе, чтобы определить, какую публикацию ищет пользователь.

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

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

| submissionId | stringId 
+--------------+----------
| 1            | rbMZV    
+--------------+----------
| 2            | MQyPi    
+--------------+----------
| NULL         | hfXL7

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

Ответы [ 6 ]

0 голосов
/ 10 июля 2018

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

INSERT cust  (CustomerID, Company, Fax)  VALUES   (NEWID(), 'Wartian Herkku','981-443655'); 

Если вы решите использовать его, я бы предложил использовать newsequentialid () вместо newid (), причина выигрыш в производительности от seq id

0 голосов
/ 10 июля 2018

Как сказал Ганс Пассант в комментариях, простая стратегия состоит в том, чтобы base64-кодировать ваш автоинкрементный первичный ключ в URL.

Более безопасным вариантом этого является использование блочного шифра для шифрования значения первичного ключа, а затем кодирование результата base64 в ваших URL-адресах. Это имеет преимущество фиксированной длины.

Я успешно использовал Skip32 (разновидность алгоритма Skipjack) в проектах для этой цели.

0 голосов
/ 09 июля 2018

Я ставлю под сомнение ваше утверждение

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

Индексы SQL (уникальные или иные) обычно хранятся в B-Trees , поэтому да, он будет работать медленнее, но не заметно, пока вы не превысите количество записей индекса, которые могут быть полностью загружены в ОЗУ на вашем компьютере. сервер (это было бы более uint32.max записей). В этот момент вы можете обновить сервер или просто реализовать стратегию sharding .

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

0 голосов
/ 05 июля 2018

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

CREATE TABLE [dbo].[Links]
(
    [Id] [bigint] IDENTITY(1,1) NOT NULL
  , [StringId] [nvarchar](5) NOT NULL
  , [OtherInfo] [<whatever type you need]
  , CONSTRAINT [PK_LinksId] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC
    )
)

Столбец Id в качестве кластеризованного первичного ключа поможет поддерживать скорость вставки.

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

CREATE UNIQUE NONCLUSTERED INDEX [IDX_StringId] ON [dbo].[Links]
(
    [StringId]
)

Если один и тот же stringId сгенерирован дважды, SQL его перехватит, и вы сможете сгенерировать другую случайную строку.

И чтобы избежать каких-либо неожиданных замедлений, я бы также рассмотрел установку Auto Update Statistics Asynchronously в true, чтобы запросы не блокировались, если статистика устарела и требует обновления.

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

0 голосов
/ 05 июля 2018

Вот три основных подхода:

  1. Сгенерируйте и сохраните все случайные идентификаторы заранее - достаточно много, чтобы они никогда не закончились (учитывая прогнозируемое общее количество использований). Одним из недостатков здесь может быть трудно предсказать общее количество идентификаторов, необходимых для поддержки жизненного цикла системы.
  2. Создание достаточного количества случайных идентификаторов, чтобы обеспечить более чем достаточно для установленного периода времени. Затем периодически генерируйте достаточно новых, чтобы удовлетворить прогнозируемый спрос. (Например, период времени может составлять один день, и генератор может быть запущен в какой-то момент ночью, когда спрос низок.)
  3. Генерация случайных идентификаторов на лету - только при необходимости.

Есть плюсы и минусы каждого:

  • Если хранение не является проблемой, (1), возможно, является самым простым вариантом, поскольку, как только оно сделано, оно сделано и остается навсегда - вам не придется беспокоиться о неудачных заданиях и т. Д.
  • (2) - это, в основном, ваш предложенный подход: это кажется хорошим, но есть и другие вещи, которые следует учитывать, такие как непредсказуемые скачки использования, неудачные запланированные задания и т. Д.
  • (3) также может быть простым и держать его в форме, поскольку таблица будет расти со временем, и нет необходимости прогнозировать использование. Потенциальным недостатком здесь является то, что любая такая функция будет продолжать генерировать идентификаторы до тех пор, пока не будет найден уникальный, поэтому она может стать медленнее по мере увеличения числа идентификаторов - хотя это никогда не может быть проблемой, если количество различных случайных перестановок значительно больше, чем потенциальное общее количество использований.

Демонстрация захода на посадку (3) выше

Онлайн-демонстрация того, как генератор на лету может быть реализован в MySQL: http://rextester.com/TKGPZ41053

Расчет количества перестановок

Если алфавитно-цифровые символы чувствительны к регистру, общее количество символов составляет 62. Таким образом, число возможных перестановок для каждой длины выглядит следующим образом:

Characters | Permutations
1          | 62
2          | 3844
3          | 238328
4          | 14776336
5          | 916132832
6          | 56800235584
7          | 3521614606208
8          | 218340105584896
9          | 13537086546263552
10         | 839299365868340224
0 голосов
/ 04 июля 2018

Это действительно зависит от цели, в которой вы не используете PK, и от того, как долго эти синтетические версии должны быть хороши.

То, что вы предлагаете, в порядке, хотя вы все еще выполняете работу по генерации и проверке уникальных значений. Вместо того, чтобы найти неиспользуемый, я, вероятно, сгенерировал бы submissionId заранее вместе с кодом. Два одновременных доступа к БД будут находить одну и ту же «неиспользуемую» строку (или блокировать друг друга в зависимости от того, как вы ее реализовали). Ни хорошо, ни необходимо.

Вы также можете использовать шифрование либо PK, либо PK + другие [неизменяемые] элементы строки. В мире Интернета вы можете использовать сеанс для временного и, вероятно, уникального кода для пользователя. Это действительно зависит от цели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...