Вы должны иметь возможность кодировать метку времени с точностью до секунды для диапазона времени 135 лет в 32 битах. Это займет всего 8 символов для представления в шестнадцатеричном виде. Добавлено в шестнадцатеричное представление uuid (32 шестнадцатеричных символа), которое будет содержать только 40 шестнадцатеричных символов.
Для кодирования метки времени таким способом необходимо выбрать базовый год (например, 2000) и вычислить количество дней до текущей даты (метка времени). Умножьте это количество дней на 86400, затем добавьте секунды с полуночи. Это даст вам значения, которые меньше 2 ^ 32, пока вы не достигнете 2135 года.
Обратите внимание, что вы должны сохранять начальные нули в шестнадцатеричном формате префикса метки времени, чтобы алфавитно-цифровая сортировка сохраняла хронологию.
Имея несколько битов в отметке времени, вы можете увеличить диапазон времени и / или точность. Еще 8 битов (два шестнадцатеричных символа) позволяют увеличить время до 270 лет с точностью до сотых долей секунды.
Обратите внимание, что вам не нужно моделировать долю секунд в базовом диапазоне 10. Вы получите оптимальное использование битов, разделив его на 128-е вместо 100-х для того же количества символов. С удвоением диапазона года это все еще умещается в пределах 8 бит (2 шестнадцатеричных символа)
Вероятность столкновения в пределах временной точности (то есть в секунду или на 100 или 128-ю секунды) определяется диапазоном uuid, поэтому для выбранной точности она будет равна 1 в 2 ^ 128. Увеличение точности отметки времени оказывает наибольшее влияние на снижение вероятности столкновения. Это также фактор, который оказывает наименьшее влияние на общий размер ключа.
Более эффективное кодирование символов: от 27 до 29 символов
Вы можете значительно уменьшить размер ключа, кодируя его в базе 64 вместо 16, что даст вам от 27 до 29 символов (в зависимости от вашего выбора точности)
Обратите внимание, что для части метки времени вам необходимо использовать функцию кодирования, которая принимает целое число в качестве входных данных и сохраняет последовательность сортировки цифровых символов.
Например:
def encode64(number, size):
chars = "+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
result = list()
for _ in range(size):
result.append(chars[number%64])
number //= 64
return "".join(reversed(result))
a = encode64(1234567890,6) # '-7ZU9G'
b = encode64(9876543210,6) # '7Ag-Pe'
print(a < b) # True
u = encode64(int(uuid.uuid4()),22) # '1QA2LtMg30ztnugxaokVMk'
key = a+u # '-7ZU9G1QA2LtMg30ztnugxaokVMk' (28 characters)
Вы можете сохранить еще несколько символов, объединив метку времени и uuid в одно число перед кодированием вместо объединения двух закодированных значений.
Для функции encode64 () требуется один символ каждые 6 бит.
Итак, в течение 135 лет с точностью до секунды: (32 + 128) / 6 = 26,7 -> 27 символов
вместо (32/6 = 5,3 -> 6) + (128/6 = 21,3 -> 22) ==> 28 символов
uid = uuid.uuid4()
timeStamp = daysSince2000 * 86400 + int(secondsSinceMidnight)
key = encode64( timeStamp<<128 | int(uid) ,27)
с 270-летним интервалом и 128-й точностью: (40 + 128) / 6 = 28 символов
uid = uuid.uuid4()
timeStamp = daysSince2000 * 86400 + int(secondsSinceMidnight)
precision = 128
timeStamp = timeStamp * precision + int(factionOfSecond * precision)
key = encode64( timeStamp<<128 | int(uid) ,28)
С помощью 29 символов вы можете повысить точность до 1024th секунды и диапазона года до 2160 лет .
Маскировка UUID: клавиши длиной от 17 до 19 символов
Чтобы быть еще более эффективным, вы можете удалить первые 64 бита uuid (который уже является отметкой времени) и объединить его с вашей собственной отметкой времени. Это даст вам ключи длиной от 17 до 19 символов практически без потери предотвращения столкновений (в зависимости от вашего выбора точности).
mask = (1<<64)-1
key = encode64( timeStamp<<64 | (int(uid) & mask) ,19)
Целочисленные / цифровые клавиши?
В качестве заключительного замечания: если ваша база данных поддерживает очень большие целые числа или числовые поля (140 бит или более) в качестве ключей, вам не нужно преобразовывать объединенное число в строку. Просто используйте его непосредственно как ключ. Числовая последовательность timeStamp<<128 | int(uid)
будет соответствовать хронологии.