2014-12-14 2 views
0

У меня есть стол Postgres 9.3, который имеет столбец с именем id как PKEY, id равен char(9), и разрешает только нижний регистр a-z0-9, я использую Python с psycopg для вставки в эту таблицу.Как создать случайный идентификатор?

Когда мне нужно вставить в эту таблицу, я вызываю функцию Python get_new_id(), мой вопрос в том, как сделать get_new_id() эффективным?

У меня есть следующие решения, ни один из них не удовлетворяет меня.

a) Сгенерируйте большое количество id s, сохраните их в какой-либо таблице, когда мне нужен новый идентификатор, I SELECT один из этой таблицы, а затем удалите его из этой таблицы, а затем верните этот выбранный идентификатор. Нижняя сторона этого решения заключается в том, что ему необходимо поддерживать эту таблицу, в каждом вызове get_new_id() также будет SELECT COUNT, чтобы узнать, нужно ли мне генерировать больше идентификаторов для ввода в эту таблицу.

b) Когда вызывается get_new_id(), он генерирует случайный идентификатор, а затем передает этот идентификатор в хранимую процедуру, чтобы проверить, используется ли этот идентификатор, если нет, мы хорошо, если да, сделаем b) снова. В нижней части этого решения, когда таблица становится больше, частота отказов может быть высокой, и существует вероятность того, что два вызова get_new_id() в двух процессах будут генерировать один и тот же идентификатор, скажем, 1234567, а 1234567 не используется PKEY тем не менее, поэтому при вставке один процесс завершится неудачно.

Я думаю, что это довольно старая проблема, какое идеальное решение?

Редактировать

Я думаю, что это был дан ответ, см комментарий Джон Клементс.

+0

Есть «1e14» разные 9-символьные базы-36 строк, поэтому вероятность «высокого» столкновения сомнительна. – NPE

+0

Возможно, вам удастся избежать [пользовательской последовательности] (http://www.postgresql.org/docs/8.3/static/sql-createsequence.html), начиная с произвольно большого числа, с довольно большим шагом (и, возможно, цикл), затем поставьте триггер, который вызывает 'get_new_id', который берет новый PK и создает его базовое 36. –

+0

@JonClements Не думаю, что последовательность, я думаю, это так, вы должны сделать это ответом. (Почему вы говорите «может быть» в первом предложении, есть ли какие-либо ошибки в этом решении?) –

ответ

0
select left(md5(random()::text || now()), 9); 
    left  
----------- 
c4c384561 

Сделать идентификатор первичного ключа и попробовать вставить. Если исключение выбрано, поймайте его и повторите попытку. Ничего особенного. почему только 9 символов? Сделать это полный 32.

Установите этот флажок, ответ, как сделать его меньше: https://stackoverflow.com/a/15982876/131874

+0

Мне нужно отобразить этот идентификатор, UUID или более длинную версию, не очень хорошо выглядящую. и я сомневаюсь, что влево (md5(), 9) имеет более низкое столкновение, которое просто генерирует случайные строки. –

+0

@NotanID 9 символьная строка не имеет более низкой вероятности столкновения, чем любая другая 9 символьная строка, независимо от того, как вы ее создаете. Единственный способ снизить этот шанс сделать его больше и/или добавить другие символы, как специальные или знаки препинания. _хорошо выглядит_? О чем ты говоришь? = | –

+0

@NotanID И это случайное. Вы пропустили 'random()' часть. –

1

оффтопик, потому что у вас уже есть символ (9) Тип данных:

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

PostgreSQL также может сделать это за вас, используя расширение uuid-ossp.