UUID v7 জেনারেটর
ডেটাবেস প্রাইমারি কীর জন্য টাইম-অর্ডার্ড UUID v7 তৈরি করুন
…
ফরম্যাট
UUID v7 কী?
UUID v7 হলো একটি পরবর্তী প্রজন্মের UUID ফরম্যাট যা RFC 9562 (মে ২০২৪)-এ মানকীভূত। এটি সর্বোচ্চ-গুরুত্বপূর্ণ বিটে একটি 48-বিট Unix মিলিসেকেন্ড টাইমস্ট্যাম্প এনকোড করে, তারপর ভার্সন ও ভেরিয়েন্ট মার্কার থাকে, এবং বাকি বিটগুলো ক্রিপ্টোগ্রাফিক্যালি সিকিউর র্যান্ডম ডেটায় পূর্ণ হয়।
টাইমস্ট্যাম্প উচ্চ বিট দখল করায়, UUID v7 মানগুলো কালানুক্রমিকভাবে সর্ট হয় — লেক্সিকোগ্রাফিক্যালি এবং সংখ্যাগতভাবে উভয়ভাবেই। এটি ডেটাবেস প্রাইমারি কীর জন্য একটি চমৎকার পছন্দ, যেখানে র্যান্ডম UUID (v4) B-tree ইনডেক্স ফ্র্যাগমেন্টেশন ঘটায়।
কেন র্যান্ডম UUID ডেটাবেস ইনডেক্স ফ্র্যাগমেন্ট করে
B-tree ইনডেক্স — PostgreSQL, MySQL, SQLite এবং বেশিরভাগ অন্যান্য ডেটাবেস ব্যবহার করে — রো কী মান অনুযায়ী সর্ট করে রাখে। আপনি যখন নতুন রো ইনসার্ট করেন, ডেটাবেসকে সেটিকে ইনডেক্সের মধ্যে সঠিক সর্টেড অবস্থানে স্থাপন করতে হয়।
UUID v4 (সম্পূর্ণ র্যান্ডম) দিয়ে, প্রতিটি নতুন ইনসার্ট ইনডেক্স ট্রিতে মূলত র্যান্ডম অবস্থানে যায়। এটি ডেটাবেসকে ক্রমাগত অভ্যন্তরীণ ইনডেক্স পেজ পড়তে ও পুনর্লিখন করতে বাধ্য করে, পূর্ণ পেজ বিভক্ত করে এবং অন্যগুলো অর্ধেক খালি রাখে। ফলে একটি ফ্র্যাগমেন্টেড, ফোলা ইনডেক্স তৈরি হয় যা টেবিল বাড়ার সাথে সাথে রাইট ও রিড উভয়কেই ধীর করে দেয়।
UUID v7 বিট লেআউট
UUID v7 হলো 128 বিট প্রশস্ত, ছয়টি ফিল্ডে বিভক্ত:
| বিট | ফিল্ড | উদ্দেশ্য |
|---|---|---|
| 48 | unix_ts_ms | মিলিসেকেন্ডে 48-বিট Unix টাইমস্ট্যাম্প — সম্পূর্ণ উচ্চ অর্ধেক দখল করে |
| 4 | ver | ভার্সন নম্বর — সবসময় 0111 (দশমিক ৭) |
| 12 | rand_a | ক্রিপ্টোগ্রাফিক্যালি সিকিউর র্যান্ডম ডেটার 12 বিট |
| 2 | var | ভেরিয়েন্ট মার্কার — সবসময় 10 (RFC 4122 ভেরিয়েন্ট) |
| 62 | rand_b | ক্রিপ্টোগ্রাফিক্যালি সিকিউর র্যান্ডম ডেটার 62 বিট |
টাইমস্ট্যাম্পের নির্ভুলতা ১ মিলিসেকেন্ড। একই মিলিসেকেন্ডের মধ্যে, UUID v7 মানগুলো তাদের র্যান্ডম সাফিক্স দ্বারা ক্রমানুসারী — এগুলো সাব-মিলিসেকেন্ডে একটানা বাড়তে থাকার গ্যারান্টি নেই, তবে এগুলো k-sortable: একই সময়ে তৈরি IDs ইনডেক্সে পাশাপাশি সর্ট হবে।
UUID v7 বনাম UUID v1
UUID v1 এবং UUID v7 উভয়ই একটি টাইমস্ট্যাম্প এমবেড করে, তবে ডিজাইনে উল্লেখযোগ্যভাবে আলাদা:
| বৈশিষ্ট্য | UUID v7 | UUID v1 |
|---|---|---|
| Epoch / টাইম বেস | Unix epoch (জানুয়ারি ১, ১৯৭০) | Gregorian epoch (অক্টোবর ১৫, ১৫৮২) |
| সময়ের নির্ভুলতা | ১ মিলিসেকেন্ড | ১০০ ন্যানোসেকেন্ড |
| সর্টযোগ্য | হ্যাঁ — ডিজাইন অনুযায়ী k-sortable | না — UUID লেআউটে টাইম ফিল্ড এলোমেলো |
| গোপনীয়তা | কোনো হোস্ট তথ্য ফাঁস নেই | তৈরিকারী হোস্টের MAC ঠিকানা এমবেড করে |
| DB ইনডেক্স পারফরম্যান্স | চমৎকার — ক্রমানুসারী ইনসার্ট, ন্যূনতম ফ্র্যাগমেন্টেশন | দুর্বল — টাইমস্ট্যাম্ট থাকলেও ক্রমানুসারী নয় |
| মান | RFC 9562 (২০২৪) | RFC 4122 (২০০৫) |
| নেটিভ ব্রাউজার সমর্থন | এখনো নেই (crypto.randomUUID v7 নেই) | নেটিভলি উপলব্ধ নেই |
যেকোনো নতুন প্রজেক্টে যেখানে টাইম-অর্ডার্ড UUID দরকার, UUID v1-এর বদলে UUID v7 পছন্দ করুন। UUID v1 লিগেসি এবং হোস্ট তথ্য ফাঁস করে।
UUID v7 বনাম ULID
ULID (Universally Unique Lexicographically Sortable Identifier) UUID v7-এর মতো একই সমস্যার সমাধান করে। এখানে তুলনা:
- RFC 9562 UUID মান অনুসরণ করে — সমস্ত UUID টুলিংয়ের সাথে সামঞ্জস্যপূর্ণ
- হাইফেনযুক্ত হেক্স ফরম্যাট — সর্বজনীনভাবে স্বীকৃত
- নেটিভ ডেটাবেস UUID কলাম সমর্থন
- মোট 128 বিট
- Crockford Base32 এনকোডিং — ২৬ অক্ষর, সামান্য বেশি কম্প্যাক্ট
- কেস-ইনসেনসিটিভ এবং অস্পষ্ট অক্ষর এড়ায় (I, L, O, U)
- এক নজরে বেশি মানব-পাঠযোগ্য
- একটি লাইব্রেরি প্রয়োজন — কোনো নেটিভ প্ল্যাটফর্ম সমর্থন নেই
আপনি যদি ইতিমধ্যে UUID ইকোসিস্টেমে থাকেন (PostgreSQL uuid কলাম, UUID ফেরত দেওয়া REST API), UUID v7 ব্যবহার করুন। নতুন শুরু করলে এবং আরও মানব-বান্ধব এনকোডিং পছন্দ করলে, ULID একটি যুক্তিসঙ্গত বিকল্প।
ডেটাবেসে UUID v7 ব্যবহার করা
UUID v7 এখনো বেশিরভাগ ডেটাবেসে নেটিভলি তৈরি হয় না, তবে স্ট্যান্ডার্ড UUID কলামে সংরক্ষণ করা যায় এবং অ্যাপ্লিকেশন কোড বা এক্সটেনশনের মাধ্যমে তৈরি করা যায়:
uuid কলামে সংরক্ষণ করুন। pg-uuidv7 এক্সটেনশন একটি uuid_generate_v7() সার্ভার-সাইড ফাংশন যোগ করে যদি আপনার DB-জেনারেটেড ID দরকার হয়।BINARY(16) বা CHAR(36) কলামে সংরক্ষণ করুন। অ্যাপ্লিকেশন কোডে তৈরি করুন। MySQL 8.0+-এ v1-এর জন্য UUID_TO_BIN(UUID(), 1) এর মাধ্যমে অর্ডার্ড UUID সমর্থন আছে, কিন্তু v7-এর জন্য অ্যাপ-লেভেল জেনারেশন প্রয়োজন।TEXT (৩৬ অক্ষর) বা BLOB (১৬ বাইট) হিসেবে সংরক্ষণ করুন। অ্যাপ্লিকেশন কোডে তৈরি করুন। TEXT-এ লেক্সিকোগ্রাফিক সর্ট সঠিকভাবে কাজ করে কারণ UUID v7 একটি ফিক্সড-উইডথ টাইমস্ট্যাম্প প্রিফিক্স ব্যবহার করে।কোড উদাহরণ
UUID v7 এখনো crypto.randomUUID()-এর মাধ্যমে উপলব্ধ নেই। নেটিভ সমর্থন না আসা পর্যন্ত uuidv7 (npm) এর মতো একটি লাইব্রেরি ব্যবহার করুন:
function generateUuidV7() {
const buf = new Uint8Array(16)
crypto.getRandomValues(buf)
const ms = BigInt(Date.now())
// Embed 48-bit Unix ms timestamp
buf[0] = Number((ms >> 40n) & 0xFFn)
buf[1] = Number((ms >> 32n) & 0xFFn)
buf[2] = Number((ms >> 24n) & 0xFFn)
buf[3] = Number((ms >> 16n) & 0xFFn)
buf[4] = Number((ms >> 8n) & 0xFFn)
buf[5] = Number(ms & 0xFFn)
// Set version 7 (0111xxxx)
buf[6] = (buf[6] & 0x0F) | 0x70
// Set variant (10xxxxxx)
buf[8] = (buf[8] & 0x3F) | 0x80
const hex = [...buf].map(b => b.toString(16).padStart(2, '0')).join('')
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`
}
// Node.js 20+ built-in
// import { randomUUID } from 'node:crypto' // v4 only — no v7 yet in stdlib# pip install uuid7 import uuid_extensions uid = uuid_extensions.uuid7() print(uid) # e.g. 018e2b3d-1a2b-7000-8000-abc123456789 print(uid.time) # Unix ms timestamp embedded in the UUID # Or as a plain string from uuid_extensions import uuid7str print(uuid7str())
-- PostgreSQL 13+ extension-free implementation
CREATE OR REPLACE FUNCTION uuid_generate_v7()
RETURNS uuid
LANGUAGE sql
AS $$
SELECT encode(
set_bit(
set_bit(
overlay(
uuid_send(gen_random_uuid())
PLACING substring(int8send(floor(extract(epoch FROM clock_timestamp()) * 1000)::bigint) FROM 3)
FROM 1 FOR 6
),
52, 1
),
53, 1
),
'hex'
)::uuid;
$$;
-- Usage as a default primary key
CREATE TABLE events (
id uuid PRIMARY KEY DEFAULT uuid_generate_v7(),
payload jsonb,
created_at timestamptz DEFAULT now()
);function extractTimestamp(uuid: string): Date {
const hex = uuid.replace(/-/g, '')
const ms = parseInt(hex.slice(0, 12), 16) // first 48 bits = ms timestamp
return new Date(ms)
}
const uid = '018e2b3d-1a2b-7000-8000-abc123456789'
console.log(extractTimestamp(uid).toISOString())
// → "2024-03-15T10:22:05.259Z"