2013-04-09 2 views
1

Мне нужен уникальный идентификатор (максимально уникальный) в течение месяца и в течение одного года. Код должен быть коротким. Код необходим для программного обеспечения учета как идентификационный номер записи/записи.php уникальный идентификатор в течение месяца

Цель состоит в том, чтобы сделать его уникальным, если компания в течение месяца имеет не более 10 000 транзакций. Кроме того, цель заключается в том, что код должен быть как можно короче, а также PHP-код как можно короче и использует как можно меньше ресурсов сервера.

Автоинкремент Mysql не может использоваться, например, если 10 000 транзакций в месяц, то через несколько лет число будет очень длинным.

На данный момент решили использовать такие

date("m"). '-' .substr(md5(uniqid(rand(), true)), -20, 4); 

Имеете ли лучшее решение?

+1

и что после месяца? Я бы префикс его тоже год –

+2

Почему случайный идентификатор вместо «инкрементного числового идентификатора» сбрасывается до 0 в начале каждого месяца? Только с 4 случайными символами (0-9 a-f) риск «столкновения» выглядит относительно высоким. –

+0

Полагаю, год не нужен, потому что было бы очень долго. Бухгалтеру или бухгалтеру необходимо написать его на каждом документе. Таким образом, идентификатор должен быть как можно короче. Если тот же идентификатор будет в 2013 и 2014 годах, я думаю, что это не проблема. Идентификатор необходимо найти в программном обеспечении. Таковы наши требования законодательства. Кто-то видит id в документе и спрашивает бухгалтера: покажите мне, где он записан в программном обеспечении. – user2232696

ответ

11

Я бы сказал, что вы обманываете себя. Стандартный автоинкремент mysql (INT) достигнет 4 294 967 296. Таким образом, по ставке 10 тыс. Транзакций в месяц, это будет продолжаться только в течение 35 791 год.

Теперь, конечно, если этого недостаточно, вы можете использовать BIGINT, и в этом случае у вас будет 153,722,867,280,912 лет, чтобы разобраться. Это в несколько раз дольше, чем предсказанная продолжительность жизни Вселенной.

Это точный вариант использования для автоматического приращения.

+0

+1, OMG Lolw't ... я уверен, что умру до 35791 года. –

+0

Лучший ответ когда-либо :) Вы заслуживаете cookie –

0
date("m").'-'.time().rand(0,9999) 

будет достаточно, я думаю.

+0

нет. этого не будет. прочитайте парадокс дня рождения: http://en.wikipedia.org/wiki/Birthday_problem –

+0

Абсолютно не парадокс дня рождения делает это МНОГО менее успешным, чем вы ожидаете. –

+0

у вас есть время() - уникальная 10-значная цифра за каждую секунду и случайное число от 0 до 9999. Вы получите дубликат только в случаях, когда у вас более сотни запросов в секунду. –

-1

Как насчет того, чтобы использовать идентификатор компании, который, я уверен, у вас есть, с месяцем/годом и md5, а затем возьмите первые 10 символов. Это всегда будет уникальным.

+0

и не будет иметь преимущество над автоматическим приращением вообще. – Nanne

+0

Не обязательно верно. Проверьте http://www.mscs.dal.ca/~selinger/md5collision/ –

+0

Не будет ли это генерировать одинаковый идентификатор в течение всего месяца? Вопрос заключался в том, чтобы спросить о наличии 10 000 уникальных идентификаторов в течение месяца. – MrGlass

1

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

+0

Любая функция, которая выводит конечный набор значений, не может гарантировать уникальность, просто FYI. На самом деле существует принцип, который прямо противоречит вашим требованиям: http://en.wikipedia.org/wiki/Pigeonhole_principle –

+0

a) Они уже используют 'uniqid'. b) Если вы собираетесь заявить, что он на 100% уникален, подайте доказательство, поскольку оно не соответствует этому требованию. – Jon

+0

Вы правы, мои извинения. 100% не совсем верно - хотя для этого варианта использования (<10000/месяц) это было бы. – MrGlass

3

После лет ваш ID будет 50x12x10.000 = 6.000.000. Это очень маленький идентификатор для mysql.

Если вы не хотите, чтобы показать, что длинный идентификатор для пользователей вы можете сделать dechex

$userFriendlyId = dechex($id); 

и делать запросы с удобным ид с hexdec

die(dechex(6000000)); //will output 5b8d80 

Или другой converting, спасибо к Джону.

+0

Или какая-то другая форма преобразования базы, чтобы получить еще больше букв, но dechex с волей. –

+0

Конечно, это как раз к примеру. – Narek

0

Я хотел бы предложить несколько цифр хэша

$random_hash = substr(md5(uniqid(rand(), true)), 10, 10); 
echo date('m-Y-').$random_hash ; 

, но я этого не делаю. Комбинация уникального первичного ключа с датой ('m-Y') на выходе может быть намного лучше по причинам бухгалтерского учета.

3

Прежде всего, я бы пошел на автоматическое увеличение. Даже если вы решите использовать код, упомянутый (месяц + случайный материал), я бы посоветовал также использовать числовое число (int/bigint) auto increment id. Вы должны использовать этот идентификатор «под поверхностью», чтобы ваш код связывался с базой данных (ссылаясь/просматривая записи).

Так что для идентификатора «месяц + случайный материал» я бы не советовал ничего использовать с uniqid(), поскольку он основан на микросекундах и не уникален, если две транзакции будут проходить в тот же микросекунда. Также я бы отказался от использования md5(), потому что эта функция была бы очень полезна для хэширования, но сильно замедляет ваш код, если вы будете использовать его только для генерации символов.

Также ваше собственное предложение кода генерирует 4 случайных символа, которые могут быть 0-9 или a-f (шестнадцатеричные), что дает вам 16 возможностей. 4 символа из 16 вариантов дают вам 16x16x16x16 = 65 536 уникальных строк. Было бы очень возможно, что при рендеринге 10 000 из этих строк вы получили бы дубликаты.

Я бы посоветовал создать случайную строку из символов 0-9, a-z и A-Z, что дает вам 36 возможностей для каждого символа и с 4 символами дает вам 36x36x36x36 = 1,679,616 уникальных строк. Больше символов дает меньше вероятности дублирования (столкновение). Вы могли бы сделать такие вещи, как это:

function randString($length = 4) { 
    $randChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
    $randString = ''; 
    while (strlen($randString) < abs(intval($length))) { 
     $randString .= substr($randChars, rand(0, strlen($randChars)-1), 1); 
    } 
    return $randString; 
} 

$id = date('m') . randString(4); 

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

Edit: сделать некоторые тесты

Я сделал некоторые испытания на столкновение: я оказал 10000 случайных струне сто раз и проверяется уникальность каждый раз. Делается это с длиной 3, 4 (как вы это делали), 5 и 6. Так вот результаты:

-------- Length 3 ------------ 
Minimal duplicates: 170 
Maximum duplicates: 241 
Average duplicates: 207.05 
-------- Length 4 ------------ 
Minimal duplicates: 0 
Maximum duplicates: 8 
Average duplicates: 3.19 
-------- Length 5 ------------ 
Minimal duplicates: 0 
Maximum duplicates: 2 
Average duplicates: 0.05 
-------- Length 6 ------------ 
Minimal duplicates: 0 
Maximum duplicates: 0 
Average duplicates: 0 

Absolute 0% вероятность столкновения не может быть исключена, как и указывал Mark B со ссылкой к проблеме дня рождения.

Смежные вопросы