چرا UUID7 و ULID گزینههای بهتری برای کلیدهای اصلی در پایگاه داده هستند؟
البته اگر Auto-Increment مناسب کار ما نباشد

💡 راهحل سنتی چیست؟
استفاده از UUID (نسخه ۴) بهعنوان کلید اصلی مزایای خوبی دارد: یکتایی جهانی بدون نیاز به هماهنگی بین سرورها، مناسب برای محیطهای توزیعشده، و جلوگیری از افشای الگوهای داده. اما یک مشکل جدی دارد.
🔍 چرا UUID تصادفی (مثلاً UUIDv4) در دیتابیسها عملکرد خوبی ندارد؟
اکثر پایگاههای داده رابطهای مانند PostgreSQL، MySQL و SQL Server برای ایندکسگذاری — مخصوصاً روی کلید اصلی — از ساختاری بهنام B-Tree (Balanced Tree) استفاده میکنند.
این ساختار کمک میکند:
✳️جستجوی کلیدها با پیچیدگی O(log n) انجام شود (سریع و مقیاسپذیر)،
✳️دادهها بهصورت مرتب نگه داشته شوند،
✳️ و درج، حذف یا بهروزرسانی بهشکل کارآمد مدیریت شود.
اما مشکل از جایی شروع میشود که کلیدهایی با ترتیب تصادفی (مثل UUIDv4) در جدول وارد میشوند.
📉 چه اتفاقی میافتد؟
وقتی دادههای زیادی با کلید تصادفی وارد جدول میشوند:
⛔️ دیتابیس نمیتواند آنها را در انتهای ساختار درختی اضافه کند (مثل auto-increment IDs)،
⛔️ باید آنها را بین صفحات مختلف B-Tree پراکنده کند،
⛔️ این پراکندگی باعث عملیات مکرر Page Split (شکستن صفحات)، جابهجایی نودها و بازچینش ساختار درختی میشود.
🧨 نتیجه؟
🧱کند شدن محسوس عملیات درج (INSERT)،
🧱 مصرف بالای I/O و حافظه،
🧱 کاهش عملکرد کلی سیستم در سناریوهای پرترافیک.
✅ راهحلهای مدرن: UUID7 و ULID
برای رفع این مشکلات، دو استاندارد جدید معرفی شدهاند:
🔹 استاندارد ULID (Lexicographically sortable): ترکیبی از timestamp و داده تصادفی
🔹 استاندارد UUIDv7: نسخهای از UUID با ترتیب زمانی، سازگار با استاندارد UUID
مزیت اصلی این دو چیست؟
🔸 با حفظ یکتایی و امنیت، کلیدها بهصورت ترتیبی در ایندکس درج میشوند.
🔸 این یعنی:
✅کاهش شدید Page Split و پراکندگی
✅بهبود درجهای پرترافیک
✅جستوجوی سریعتر بر اساس بازههای زمانی
📐 قالب ULID
ULID یک رشته ۲۶ نویسهای است که با Crockford’s Base32 کدگذاری میشود (حروف I, L, O, U حذف شدهاند تا اشتباه نشوند).
→ طول: ۲۶ نویسه – کاراکترهای ابتدایی مهرزمان هستند.
→ مثال: ۰۱AN4Z07BY79KA1307SR9X4MV3
📐 قالب UUIDv7
→ نمایش بهصورت استاندارد UUID در مبنای ۱۶ (hex) با خط تیره
→ طول شامل خط تیره: ۳۶ نویسه – کاراکترهای ابتدایی مهرزمان هستند.
→ قالب: ۸-۴-۴-۴-۱۲
→ مثال: ۰۱۷f45e0-7e1a-7a3f-8bbc-4dbf7e6d9c3a
→ طول بدون خط تیره: ۳۲ نویسه hex